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

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)