stlink: add STLINK_F_HAS_JTAG_SET_FREQ
[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 return ERROR_OK;
304 }
305
306 COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base)
307 {
308 if (CMD_ARGC == 1)
309 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bcm2835_peri_base);
310 return ERROR_OK;
311 }
312
313 static const struct command_registration bcm2835gpio_command_handlers[] = {
314 {
315 .name = "bcm2835gpio_jtag_nums",
316 .handler = &bcm2835gpio_handle_jtag_gpionums,
317 .mode = COMMAND_CONFIG,
318 .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
319 .usage = "(tck tms tdi tdo)* ",
320 },
321 {
322 .name = "bcm2835gpio_tck_num",
323 .handler = &bcm2835gpio_handle_jtag_gpionum_tck,
324 .mode = COMMAND_CONFIG,
325 .help = "gpio number for tck.",
326 },
327 {
328 .name = "bcm2835gpio_tms_num",
329 .handler = &bcm2835gpio_handle_jtag_gpionum_tms,
330 .mode = COMMAND_CONFIG,
331 .help = "gpio number for tms.",
332 },
333 {
334 .name = "bcm2835gpio_tdo_num",
335 .handler = &bcm2835gpio_handle_jtag_gpionum_tdo,
336 .mode = COMMAND_CONFIG,
337 .help = "gpio number for tdo.",
338 },
339 {
340 .name = "bcm2835gpio_tdi_num",
341 .handler = &bcm2835gpio_handle_jtag_gpionum_tdi,
342 .mode = COMMAND_CONFIG,
343 .help = "gpio number for tdi.",
344 },
345 {
346 .name = "bcm2835gpio_swd_nums",
347 .handler = &bcm2835gpio_handle_swd_gpionums,
348 .mode = COMMAND_CONFIG,
349 .help = "gpio numbers for swclk, swdio. (in that order)",
350 .usage = "(swclk swdio)* ",
351 },
352 {
353 .name = "bcm2835gpio_swclk_num",
354 .handler = &bcm2835gpio_handle_swd_gpionum_swclk,
355 .mode = COMMAND_CONFIG,
356 .help = "gpio number for swclk.",
357 },
358 {
359 .name = "bcm2835gpio_swdio_num",
360 .handler = &bcm2835gpio_handle_swd_gpionum_swdio,
361 .mode = COMMAND_CONFIG,
362 .help = "gpio number for swdio.",
363 },
364 {
365 .name = "bcm2835gpio_srst_num",
366 .handler = &bcm2835gpio_handle_jtag_gpionum_srst,
367 .mode = COMMAND_CONFIG,
368 .help = "gpio number for srst.",
369 },
370 {
371 .name = "bcm2835gpio_trst_num",
372 .handler = &bcm2835gpio_handle_jtag_gpionum_trst,
373 .mode = COMMAND_CONFIG,
374 .help = "gpio number for trst.",
375 },
376 {
377 .name = "bcm2835gpio_speed_coeffs",
378 .handler = &bcm2835gpio_handle_speed_coeffs,
379 .mode = COMMAND_CONFIG,
380 .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
381 },
382 {
383 .name = "bcm2835gpio_peripheral_base",
384 .handler = &bcm2835gpio_handle_peripheral_base,
385 .mode = COMMAND_CONFIG,
386 .help = "peripheral base to access GPIOs (RPi1 0x20000000, RPi2 0x3F000000).",
387 },
388
389 COMMAND_REGISTRATION_DONE
390 };
391
392 static const char * const bcm2835_transports[] = { "jtag", "swd", NULL };
393
394 struct jtag_interface bcm2835gpio_interface = {
395 .name = "bcm2835gpio",
396 .supported = DEBUG_CAP_TMS_SEQ,
397 .execute_queue = bitbang_execute_queue,
398 .transports = bcm2835_transports,
399 .swd = &bitbang_swd,
400 .speed = bcm2835gpio_speed,
401 .khz = bcm2835gpio_khz,
402 .speed_div = bcm2835gpio_speed_div,
403 .commands = bcm2835gpio_command_handlers,
404 .init = bcm2835gpio_init,
405 .quit = bcm2835gpio_quit,
406 };
407
408 static bool bcm2835gpio_jtag_mode_possible(void)
409 {
410 if (!is_gpio_valid(tck_gpio))
411 return 0;
412 if (!is_gpio_valid(tms_gpio))
413 return 0;
414 if (!is_gpio_valid(tdi_gpio))
415 return 0;
416 if (!is_gpio_valid(tdo_gpio))
417 return 0;
418 return 1;
419 }
420
421 static bool bcm2835gpio_swd_mode_possible(void)
422 {
423 if (!is_gpio_valid(swclk_gpio))
424 return 0;
425 if (!is_gpio_valid(swdio_gpio))
426 return 0;
427 return 1;
428 }
429
430 static int bcm2835gpio_init(void)
431 {
432 bitbang_interface = &bcm2835gpio_bitbang;
433
434 LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver");
435
436 if (bcm2835gpio_jtag_mode_possible()) {
437 if (bcm2835gpio_swd_mode_possible())
438 LOG_INFO("JTAG and SWD modes enabled");
439 else
440 LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
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 4mA drive strength, slew rate limited, hysteresis on */
474 pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1;
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)