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

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)