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

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)