swd: get rid of jtag queue to assert/deassert srst
[openocd.git] / src / jtag / drivers / bcm2835gpio.c
1 /***************************************************************************
2 * Copyright (C) 2013 by Paul Fertser, fercerpav@gmail.com *
3 * *
4 * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au *
5 * Based on at91rm9200.c (c) Anders Larsen *
6 * and RPi GPIO examples by Gert van Loo & Dom *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <jtag/interface.h>
27 #include "bitbang.h"
28
29 #include <sys/mman.h>
30
31 uint32_t bcm2835_peri_base = 0x20000000;
32 #define BCM2835_GPIO_BASE (bcm2835_peri_base + 0x200000) /* GPIO controller */
33
34 #define BCM2835_PADS_GPIO_0_27 (bcm2835_peri_base + 0x100000)
35 #define BCM2835_PADS_GPIO_0_27_OFFSET (0x2c / 4)
36
37 /* GPIO setup macros */
38 #define MODE_GPIO(g) (*(pio_base+((g)/10))>>(((g)%10)*3) & 7)
39 #define INP_GPIO(g) do { *(pio_base+((g)/10)) &= ~(7<<(((g)%10)*3)); } while (0)
40 #define SET_MODE_GPIO(g, m) do { /* clear the mode bits first, then set as necessary */ \
41 INP_GPIO(g); \
42 *(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0)
43 #define OUT_GPIO(g) SET_MODE_GPIO(g, 1)
44
45 #define GPIO_SET (*(pio_base+7)) /* sets bits which are 1, ignores bits which are 0 */
46 #define GPIO_CLR (*(pio_base+10)) /* clears bits which are 1, ignores bits which are 0 */
47 #define GPIO_LEV (*(pio_base+13)) /* current level of the pin */
48
49 static int dev_mem_fd;
50 static volatile uint32_t *pio_base;
51
52 static bb_value_t bcm2835gpio_read(void);
53 static int bcm2835gpio_write(int tck, int tms, int tdi);
54
55 static int bcm2835_swdio_read(void);
56 static void bcm2835_swdio_drive(bool is_output);
57
58 static int bcm2835gpio_init(void);
59 static int bcm2835gpio_quit(void);
60
61 static struct bitbang_interface bcm2835gpio_bitbang = {
62 .read = bcm2835gpio_read,
63 .write = bcm2835gpio_write,
64 .swdio_read = bcm2835_swdio_read,
65 .swdio_drive = bcm2835_swdio_drive,
66 .blink = NULL
67 };
68
69 /* GPIO numbers for each signal. Negative values are invalid */
70 static int tck_gpio = -1;
71 static int tck_gpio_mode;
72 static int tms_gpio = -1;
73 static int tms_gpio_mode;
74 static int tdi_gpio = -1;
75 static int tdi_gpio_mode;
76 static int tdo_gpio = -1;
77 static int tdo_gpio_mode;
78 static int trst_gpio = -1;
79 static int trst_gpio_mode;
80 static int srst_gpio = -1;
81 static int srst_gpio_mode;
82 static int swclk_gpio = -1;
83 static int swclk_gpio_mode;
84 static int swdio_gpio = -1;
85 static int swdio_gpio_mode;
86
87 /* Transition delay coefficients */
88 static int speed_coeff = 113714;
89 static int speed_offset = 28;
90 static unsigned int jtag_delay;
91
92 static bb_value_t bcm2835gpio_read(void)
93 {
94 return (GPIO_LEV & 1<<tdo_gpio) ? BB_HIGH : BB_LOW;
95 }
96
97 static int bcm2835gpio_write(int tck, int tms, int tdi)
98 {
99 uint32_t set = tck<<tck_gpio | tms<<tms_gpio | tdi<<tdi_gpio;
100 uint32_t clear = !tck<<tck_gpio | !tms<<tms_gpio | !tdi<<tdi_gpio;
101
102 GPIO_SET = set;
103 GPIO_CLR = clear;
104
105 for (unsigned int i = 0; i < jtag_delay; i++)
106 asm volatile ("");
107
108 return ERROR_OK;
109 }
110
111 static int bcm2835gpio_swd_write(int tck, int tms, int tdi)
112 {
113 uint32_t set = tck<<swclk_gpio | tdi<<swdio_gpio;
114 uint32_t clear = !tck<<swclk_gpio | !tdi<<swdio_gpio;
115
116 GPIO_SET = set;
117 GPIO_CLR = clear;
118
119 for (unsigned int i = 0; i < jtag_delay; i++)
120 asm volatile ("");
121
122 return ERROR_OK;
123 }
124
125 /* (1) assert or (0) deassert reset lines */
126 static int bcm2835gpio_reset(int trst, int srst)
127 {
128 uint32_t set = 0;
129 uint32_t clear = 0;
130
131 if (trst_gpio > 0) {
132 set |= !trst<<trst_gpio;
133 clear |= trst<<trst_gpio;
134 }
135
136 if (srst_gpio > 0) {
137 set |= !srst<<srst_gpio;
138 clear |= srst<<srst_gpio;
139 }
140
141 GPIO_SET = set;
142 GPIO_CLR = clear;
143
144 return ERROR_OK;
145 }
146
147 static void bcm2835_swdio_drive(bool is_output)
148 {
149 if (is_output)
150 OUT_GPIO(swdio_gpio);
151 else
152 INP_GPIO(swdio_gpio);
153 }
154
155 static int bcm2835_swdio_read(void)
156 {
157 return !!(GPIO_LEV & 1 << swdio_gpio);
158 }
159
160 static int bcm2835gpio_khz(int khz, int *jtag_speed)
161 {
162 if (!khz) {
163 LOG_DEBUG("RCLK not supported");
164 return ERROR_FAIL;
165 }
166 *jtag_speed = speed_coeff/khz - speed_offset;
167 if (*jtag_speed < 0)
168 *jtag_speed = 0;
169 return ERROR_OK;
170 }
171
172 static int bcm2835gpio_speed_div(int speed, int *khz)
173 {
174 *khz = speed_coeff/(speed + speed_offset);
175 return ERROR_OK;
176 }
177
178 static int bcm2835gpio_speed(int speed)
179 {
180 jtag_delay = speed;
181 return ERROR_OK;
182 }
183
184 static int is_gpio_valid(int gpio)
185 {
186 return gpio >= 0 && gpio <= 53;
187 }
188
189 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionums)
190 {
191 if (CMD_ARGC == 4) {
192 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
193 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio);
194 COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio);
195 COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio);
196 } else if (CMD_ARGC != 0) {
197 return ERROR_COMMAND_SYNTAX_ERROR;
198 }
199
200 command_print(CMD,
201 "BCM2835 GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
202 tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
203
204 return ERROR_OK;
205 }
206
207 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tck)
208 {
209 if (CMD_ARGC == 1)
210 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
211
212 command_print(CMD, "BCM2835 GPIO config: tck = %d", tck_gpio);
213 return ERROR_OK;
214 }
215
216 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tms)
217 {
218 if (CMD_ARGC == 1)
219 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio);
220
221 command_print(CMD, "BCM2835 GPIO config: tms = %d", tms_gpio);
222 return ERROR_OK;
223 }
224
225 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdo)
226 {
227 if (CMD_ARGC == 1)
228 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio);
229
230 command_print(CMD, "BCM2835 GPIO config: tdo = %d", tdo_gpio);
231 return ERROR_OK;
232 }
233
234 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdi)
235 {
236 if (CMD_ARGC == 1)
237 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio);
238
239 command_print(CMD, "BCM2835 GPIO config: tdi = %d", tdi_gpio);
240 return ERROR_OK;
241 }
242
243 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_srst)
244 {
245 if (CMD_ARGC == 1)
246 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio);
247
248 command_print(CMD, "BCM2835 GPIO config: srst = %d", srst_gpio);
249 return ERROR_OK;
250 }
251
252 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_trst)
253 {
254 if (CMD_ARGC == 1)
255 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio);
256
257 command_print(CMD, "BCM2835 GPIO config: trst = %d", trst_gpio);
258 return ERROR_OK;
259 }
260
261 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionums)
262 {
263 if (CMD_ARGC == 2) {
264 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
265 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio);
266 } else if (CMD_ARGC != 0) {
267 return ERROR_COMMAND_SYNTAX_ERROR;
268 }
269
270 command_print(CMD,
271 "BCM2835 GPIO nums: swclk = %d, swdio = %d",
272 swclk_gpio, swdio_gpio);
273
274 return ERROR_OK;
275 }
276
277 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionum_swclk)
278 {
279 if (CMD_ARGC == 1)
280 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
281
282 command_print(CMD, "BCM2835 num: swclk = %d", swclk_gpio);
283 return ERROR_OK;
284 }
285
286 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionum_swdio)
287 {
288 if (CMD_ARGC == 1)
289 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio);
290
291 command_print(CMD, "BCM2835 num: swdio = %d", swdio_gpio);
292 return ERROR_OK;
293 }
294
295 COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs)
296 {
297 if (CMD_ARGC == 2) {
298 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff);
299 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset);
300 }
301
302 command_print(CMD, "BCM2835 GPIO: speed_coeffs = %d, speed_offset = %d",
303 speed_coeff, speed_offset);
304 return ERROR_OK;
305 }
306
307 COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base)
308 {
309 if (CMD_ARGC == 1)
310 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bcm2835_peri_base);
311
312 command_print(CMD, "BCM2835 GPIO: peripheral_base = 0x%08x",
313 bcm2835_peri_base);
314 return ERROR_OK;
315 }
316
317 static const struct command_registration bcm2835gpio_command_handlers[] = {
318 {
319 .name = "bcm2835gpio_jtag_nums",
320 .handler = &bcm2835gpio_handle_jtag_gpionums,
321 .mode = COMMAND_CONFIG,
322 .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
323 .usage = "[tck tms tdi tdo]",
324 },
325 {
326 .name = "bcm2835gpio_tck_num",
327 .handler = &bcm2835gpio_handle_jtag_gpionum_tck,
328 .mode = COMMAND_CONFIG,
329 .help = "gpio number for tck.",
330 .usage = "[tck]",
331 },
332 {
333 .name = "bcm2835gpio_tms_num",
334 .handler = &bcm2835gpio_handle_jtag_gpionum_tms,
335 .mode = COMMAND_CONFIG,
336 .help = "gpio number for tms.",
337 .usage = "[tms]",
338 },
339 {
340 .name = "bcm2835gpio_tdo_num",
341 .handler = &bcm2835gpio_handle_jtag_gpionum_tdo,
342 .mode = COMMAND_CONFIG,
343 .help = "gpio number for tdo.",
344 .usage = "[tdo]",
345 },
346 {
347 .name = "bcm2835gpio_tdi_num",
348 .handler = &bcm2835gpio_handle_jtag_gpionum_tdi,
349 .mode = COMMAND_CONFIG,
350 .help = "gpio number for tdi.",
351 .usage = "[tdi]",
352 },
353 {
354 .name = "bcm2835gpio_swd_nums",
355 .handler = &bcm2835gpio_handle_swd_gpionums,
356 .mode = COMMAND_CONFIG,
357 .help = "gpio numbers for swclk, swdio. (in that order)",
358 .usage = "[swclk swdio]",
359 },
360 {
361 .name = "bcm2835gpio_swclk_num",
362 .handler = &bcm2835gpio_handle_swd_gpionum_swclk,
363 .mode = COMMAND_CONFIG,
364 .help = "gpio number for swclk.",
365 .usage = "[swclk]",
366 },
367 {
368 .name = "bcm2835gpio_swdio_num",
369 .handler = &bcm2835gpio_handle_swd_gpionum_swdio,
370 .mode = COMMAND_CONFIG,
371 .help = "gpio number for swdio.",
372 .usage = "[swdio]",
373 },
374 {
375 .name = "bcm2835gpio_srst_num",
376 .handler = &bcm2835gpio_handle_jtag_gpionum_srst,
377 .mode = COMMAND_CONFIG,
378 .help = "gpio number for srst.",
379 .usage = "[srst]",
380 },
381 {
382 .name = "bcm2835gpio_trst_num",
383 .handler = &bcm2835gpio_handle_jtag_gpionum_trst,
384 .mode = COMMAND_CONFIG,
385 .help = "gpio number for trst.",
386 .usage = "[trst]",
387 },
388 {
389 .name = "bcm2835gpio_speed_coeffs",
390 .handler = &bcm2835gpio_handle_speed_coeffs,
391 .mode = COMMAND_CONFIG,
392 .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
393 .usage = "[SPEED_COEFF SPEED_OFFSET]",
394 },
395 {
396 .name = "bcm2835gpio_peripheral_base",
397 .handler = &bcm2835gpio_handle_peripheral_base,
398 .mode = COMMAND_CONFIG,
399 .help = "peripheral base to access GPIOs (RPi1 0x20000000, RPi2 0x3F000000).",
400 .usage = "[base]",
401 },
402
403 COMMAND_REGISTRATION_DONE
404 };
405
406 static const char * const bcm2835_transports[] = { "jtag", "swd", NULL };
407
408 struct jtag_interface bcm2835gpio_interface = {
409 .name = "bcm2835gpio",
410 .supported = DEBUG_CAP_TMS_SEQ,
411 .execute_queue = bitbang_execute_queue,
412 .transports = bcm2835_transports,
413 .swd = &bitbang_swd,
414 .speed = bcm2835gpio_speed,
415 .khz = bcm2835gpio_khz,
416 .speed_div = bcm2835gpio_speed_div,
417 .commands = bcm2835gpio_command_handlers,
418 .init = bcm2835gpio_init,
419 .quit = bcm2835gpio_quit,
420 .reset = bcm2835gpio_reset,
421 };
422
423 static bool bcm2835gpio_jtag_mode_possible(void)
424 {
425 if (!is_gpio_valid(tck_gpio))
426 return 0;
427 if (!is_gpio_valid(tms_gpio))
428 return 0;
429 if (!is_gpio_valid(tdi_gpio))
430 return 0;
431 if (!is_gpio_valid(tdo_gpio))
432 return 0;
433 return 1;
434 }
435
436 static bool bcm2835gpio_swd_mode_possible(void)
437 {
438 if (!is_gpio_valid(swclk_gpio))
439 return 0;
440 if (!is_gpio_valid(swdio_gpio))
441 return 0;
442 return 1;
443 }
444
445 static int bcm2835gpio_init(void)
446 {
447 bitbang_interface = &bcm2835gpio_bitbang;
448
449 LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver");
450
451 if (bcm2835gpio_jtag_mode_possible()) {
452 if (bcm2835gpio_swd_mode_possible())
453 LOG_INFO("JTAG and SWD modes enabled");
454 else
455 LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
456 } else if (bcm2835gpio_swd_mode_possible()) {
457 LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)");
458 } else {
459 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode");
460 return ERROR_JTAG_INIT_FAILED;
461 }
462
463 dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
464 if (dev_mem_fd < 0) {
465 perror("open");
466 return ERROR_JTAG_INIT_FAILED;
467 }
468
469 pio_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
470 MAP_SHARED, dev_mem_fd, BCM2835_GPIO_BASE);
471
472 if (pio_base == MAP_FAILED) {
473 perror("mmap");
474 close(dev_mem_fd);
475 return ERROR_JTAG_INIT_FAILED;
476 }
477
478 static volatile uint32_t *pads_base;
479 pads_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
480 MAP_SHARED, dev_mem_fd, BCM2835_PADS_GPIO_0_27);
481
482 if (pads_base == MAP_FAILED) {
483 perror("mmap");
484 close(dev_mem_fd);
485 return ERROR_JTAG_INIT_FAILED;
486 }
487
488 /* set 4mA drive strength, slew rate limited, hysteresis on */
489 pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1;
490
491 tdo_gpio_mode = MODE_GPIO(tdo_gpio);
492 tdi_gpio_mode = MODE_GPIO(tdi_gpio);
493 tck_gpio_mode = MODE_GPIO(tck_gpio);
494 tms_gpio_mode = MODE_GPIO(tms_gpio);
495 swclk_gpio_mode = MODE_GPIO(swclk_gpio);
496 swdio_gpio_mode = MODE_GPIO(swdio_gpio);
497 /*
498 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
499 * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
500 */
501 INP_GPIO(tdo_gpio);
502
503 GPIO_CLR = 1<<tdi_gpio | 1<<tck_gpio | 1<<swdio_gpio | 1<<swclk_gpio;
504 GPIO_SET = 1<<tms_gpio;
505
506 OUT_GPIO(tdi_gpio);
507 OUT_GPIO(tck_gpio);
508 OUT_GPIO(tms_gpio);
509 OUT_GPIO(swclk_gpio);
510 OUT_GPIO(swdio_gpio);
511 if (trst_gpio != -1) {
512 trst_gpio_mode = MODE_GPIO(trst_gpio);
513 GPIO_SET = 1 << trst_gpio;
514 OUT_GPIO(trst_gpio);
515 }
516 if (srst_gpio != -1) {
517 srst_gpio_mode = MODE_GPIO(srst_gpio);
518 GPIO_SET = 1 << srst_gpio;
519 OUT_GPIO(srst_gpio);
520 }
521
522 LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
523 "tdo %d trst %d srst %d", tck_gpio_mode, tms_gpio_mode,
524 tdi_gpio_mode, tdo_gpio_mode, trst_gpio_mode, srst_gpio_mode);
525
526 if (swd_mode) {
527 bcm2835gpio_bitbang.write = bcm2835gpio_swd_write;
528 bitbang_switch_to_swd();
529 }
530
531 return ERROR_OK;
532 }
533
534 static int bcm2835gpio_quit(void)
535 {
536 SET_MODE_GPIO(tdo_gpio, tdo_gpio_mode);
537 SET_MODE_GPIO(tdi_gpio, tdi_gpio_mode);
538 SET_MODE_GPIO(tck_gpio, tck_gpio_mode);
539 SET_MODE_GPIO(tms_gpio, tms_gpio_mode);
540 SET_MODE_GPIO(swclk_gpio, swclk_gpio_mode);
541 SET_MODE_GPIO(swdio_gpio, swdio_gpio_mode);
542 if (trst_gpio != -1)
543 SET_MODE_GPIO(trst_gpio, trst_gpio_mode);
544 if (srst_gpio != -1)
545 SET_MODE_GPIO(srst_gpio, srst_gpio_mode);
546
547 return ERROR_OK;
548 }

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)