OpenOCD
imx_gpio.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2017 by Grzegorz Kostka, kostka.grzegorz@gmail.com *
5  * *
6  * Based on bcm2835gpio.c *
7  ***************************************************************************/
8 
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12 
13 #include <jtag/interface.h>
14 #include <transport/transport.h>
15 #include "bitbang.h"
16 
17 #include <sys/mman.h>
18 
19 #define IMX_GPIO_BASE 0x0209c000
20 #define IMX_GPIO_SIZE 0x00004000
21 #define IMX_GPIO_REGS_COUNT 8
22 
24 
25 struct imx_gpio_regs {
26  uint32_t dr;
27  uint32_t gdir;
28  uint32_t psr;
29  uint32_t icr1;
30  uint32_t icr2;
31  uint32_t imr;
32  uint32_t isr;
33  uint32_t edge_sel;
34 } __attribute__((aligned(IMX_GPIO_SIZE)));
35 
36 static int dev_mem_fd;
37 static volatile struct imx_gpio_regs *pio_base;
38 
39 /* GPIO setup functions */
40 static inline bool gpio_mode_get(int g)
41 {
42  return pio_base[g / 32].gdir >> (g & 0x1F) & 1;
43 }
44 
45 static inline void gpio_mode_input_set(int g)
46 {
47  pio_base[g / 32].gdir &= ~(1u << (g & 0x1F));
48 }
49 
50 static inline void gpio_mode_output_set(int g)
51 {
52  pio_base[g / 32].gdir |= (1u << (g & 0x1F));
53 }
54 
55 static inline void gpio_mode_set(int g, int m)
56 {
58 }
59 
60 static inline void gpio_set(int g)
61 {
62  pio_base[g / 32].dr |= (1u << (g & 0x1F));
63 }
64 
65 static inline void gpio_clear(int g)
66 {
67  pio_base[g / 32].dr &= ~(1u << (g & 0x1F));
68 }
69 
70 static inline bool gpio_level(int g)
71 {
72  return pio_base[g / 32].dr >> (g & 0x1F) & 1;
73 }
74 
75 static bb_value_t imx_gpio_read(void);
76 static int imx_gpio_write(int tck, int tms, int tdi);
77 
78 static int imx_gpio_swdio_read(void);
79 static void imx_gpio_swdio_drive(bool is_output);
80 static int imx_gpio_swd_write(int swclk, int swdio);
81 
82 static int imx_gpio_init(void);
83 static int imx_gpio_quit(void);
84 
85 static struct bitbang_interface imx_gpio_bitbang = {
87  .write = imx_gpio_write,
88  .swdio_read = imx_gpio_swdio_read,
89  .swdio_drive = imx_gpio_swdio_drive,
90  .swd_write = imx_gpio_swd_write,
91  .blink = NULL
92 };
93 
94 /* GPIO numbers for each signal. Negative values are invalid */
95 static int tck_gpio = -1;
96 static int tck_gpio_mode;
97 static int tms_gpio = -1;
98 static int tms_gpio_mode;
99 static int tdi_gpio = -1;
100 static int tdi_gpio_mode;
101 static int tdo_gpio = -1;
102 static int tdo_gpio_mode;
103 static int trst_gpio = -1;
104 static int trst_gpio_mode;
105 static int srst_gpio = -1;
106 static int srst_gpio_mode;
107 static int swclk_gpio = -1;
108 static int swclk_gpio_mode;
109 static int swdio_gpio = -1;
110 static int swdio_gpio_mode;
111 
112 /* Transition delay coefficients. Tuned for IMX6UL 528MHz. Adjusted
113  * experimentally for:10kHz, 100Khz, 500KHz. Speeds above 800Khz are impossible
114  * to reach via memory mapped method (at least for IMX6UL@528MHz).
115  * Measured mmap raw GPIO toggling speed on IMX6UL@528MHz: 1.3MHz.
116  */
117 static int speed_coeff = 50000;
118 static int speed_offset = 100;
119 static unsigned int jtag_delay;
120 
122 {
123  return gpio_level(tdo_gpio) ? BB_HIGH : BB_LOW;
124 }
125 
126 static int imx_gpio_write(int tck, int tms, int tdi)
127 {
131 
132  for (unsigned int i = 0; i < jtag_delay; i++)
133  asm volatile ("");
134 
135  return ERROR_OK;
136 }
137 
138 static int imx_gpio_swd_write(int swclk, int swdio)
139 {
142 
143  for (unsigned int i = 0; i < jtag_delay; i++)
144  asm volatile ("");
145 
146  return ERROR_OK;
147 }
148 
149 /* (1) assert or (0) deassert reset lines */
150 static int imx_gpio_reset(int trst, int srst)
151 {
152  if (trst_gpio != -1)
154 
155  if (srst_gpio != -1)
157 
158  return ERROR_OK;
159 }
160 
161 static void imx_gpio_swdio_drive(bool is_output)
162 {
163  if (is_output)
165  else
167 }
168 
169 static int imx_gpio_swdio_read(void)
170 {
171  return gpio_level(swdio_gpio);
172 }
173 
174 static int imx_gpio_khz(int khz, int *jtag_speed)
175 {
176  if (!khz) {
177  LOG_DEBUG("RCLK not supported");
178  return ERROR_FAIL;
179  }
180  *jtag_speed = speed_coeff/khz - speed_offset;
181  if (*jtag_speed < 0)
182  *jtag_speed = 0;
183  return ERROR_OK;
184 }
185 
186 static int imx_gpio_speed_div(int speed, int *khz)
187 {
188  *khz = speed_coeff/(speed + speed_offset);
189  return ERROR_OK;
190 }
191 
192 static int imx_gpio_speed(int speed)
193 {
194  jtag_delay = speed;
195  return ERROR_OK;
196 }
197 
198 static int is_gpio_valid(int gpio)
199 {
200  return gpio >= 0 && gpio < 32 * IMX_GPIO_REGS_COUNT;
201 }
202 
203 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionums)
204 {
205  if (CMD_ARGC == 4) {
210  } else if (CMD_ARGC != 0) {
212  }
213 
215  "imx_gpio GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
217 
218  return ERROR_OK;
219 }
220 
221 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tck)
222 {
223  if (CMD_ARGC == 1)
225 
226  command_print(CMD, "imx_gpio GPIO config: tck = %d", tck_gpio);
227  return ERROR_OK;
228 }
229 
230 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tms)
231 {
232  if (CMD_ARGC == 1)
234 
235  command_print(CMD, "imx_gpio GPIO config: tms = %d", tms_gpio);
236  return ERROR_OK;
237 }
238 
239 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdo)
240 {
241  if (CMD_ARGC == 1)
243 
244  command_print(CMD, "imx_gpio GPIO config: tdo = %d", tdo_gpio);
245  return ERROR_OK;
246 }
247 
248 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdi)
249 {
250  if (CMD_ARGC == 1)
252 
253  command_print(CMD, "imx_gpio GPIO config: tdi = %d", tdi_gpio);
254  return ERROR_OK;
255 }
256 
257 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_srst)
258 {
259  if (CMD_ARGC == 1)
261 
262  command_print(CMD, "imx_gpio GPIO config: srst = %d", srst_gpio);
263  return ERROR_OK;
264 }
265 
266 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_trst)
267 {
268  if (CMD_ARGC == 1)
270 
271  command_print(CMD, "imx_gpio GPIO config: trst = %d", trst_gpio);
272  return ERROR_OK;
273 }
274 
275 COMMAND_HANDLER(imx_gpio_handle_swd_gpionums)
276 {
277  if (CMD_ARGC == 2) {
280  } else if (CMD_ARGC != 0) {
282  }
283 
285  "imx_gpio GPIO nums: swclk = %d, swdio = %d",
287 
288  return ERROR_OK;
289 }
290 
291 COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swclk)
292 {
293  if (CMD_ARGC == 1)
295 
296  command_print(CMD, "imx_gpio num: swclk = %d", swclk_gpio);
297  return ERROR_OK;
298 }
299 
300 COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swdio)
301 {
302  if (CMD_ARGC == 1)
304 
305  command_print(CMD, "imx_gpio num: swdio = %d", swdio_gpio);
306  return ERROR_OK;
307 }
308 
309 COMMAND_HANDLER(imx_gpio_handle_speed_coeffs)
310 {
311  if (CMD_ARGC == 2) {
314  }
315 
316  command_print(CMD, "imx_gpio: speed_coeffs = %d, speed_offset = %d",
318  return ERROR_OK;
319 }
320 
321 COMMAND_HANDLER(imx_gpio_handle_peripheral_base)
322 {
323  if (CMD_ARGC == 1)
325 
326  command_print(CMD, "imx_gpio: peripheral_base = 0x%08x",
328  return ERROR_OK;
329 }
330 
331 static const struct command_registration imx_gpio_command_handlers[] = {
332  {
333  .name = "imx_gpio_jtag_nums",
334  .handler = &imx_gpio_handle_jtag_gpionums,
335  .mode = COMMAND_CONFIG,
336  .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
337  .usage = "[tck tms tdi tdo]",
338  },
339  {
340  .name = "imx_gpio_tck_num",
341  .handler = &imx_gpio_handle_jtag_gpionum_tck,
342  .mode = COMMAND_CONFIG,
343  .help = "gpio number for tck.",
344  .usage = "[tck]",
345  },
346  {
347  .name = "imx_gpio_tms_num",
348  .handler = &imx_gpio_handle_jtag_gpionum_tms,
349  .mode = COMMAND_CONFIG,
350  .help = "gpio number for tms.",
351  .usage = "[tms]",
352  },
353  {
354  .name = "imx_gpio_tdo_num",
355  .handler = &imx_gpio_handle_jtag_gpionum_tdo,
356  .mode = COMMAND_CONFIG,
357  .help = "gpio number for tdo.",
358  .usage = "[tdo]",
359  },
360  {
361  .name = "imx_gpio_tdi_num",
362  .handler = &imx_gpio_handle_jtag_gpionum_tdi,
363  .mode = COMMAND_CONFIG,
364  .help = "gpio number for tdi.",
365  .usage = "[tdi]",
366  },
367  {
368  .name = "imx_gpio_swd_nums",
369  .handler = &imx_gpio_handle_swd_gpionums,
370  .mode = COMMAND_CONFIG,
371  .help = "gpio numbers for swclk, swdio. (in that order)",
372  .usage = "[swclk swdio]",
373  },
374  {
375  .name = "imx_gpio_swclk_num",
376  .handler = &imx_gpio_handle_swd_gpionum_swclk,
377  .mode = COMMAND_CONFIG,
378  .help = "gpio number for swclk.",
379  .usage = "[swclk]",
380  },
381  {
382  .name = "imx_gpio_swdio_num",
383  .handler = &imx_gpio_handle_swd_gpionum_swdio,
384  .mode = COMMAND_CONFIG,
385  .help = "gpio number for swdio.",
386  .usage = "[swdio]",
387  },
388  {
389  .name = "imx_gpio_srst_num",
390  .handler = &imx_gpio_handle_jtag_gpionum_srst,
391  .mode = COMMAND_CONFIG,
392  .help = "gpio number for srst.",
393  .usage = "[srst]",
394  },
395  {
396  .name = "imx_gpio_trst_num",
397  .handler = &imx_gpio_handle_jtag_gpionum_trst,
398  .mode = COMMAND_CONFIG,
399  .help = "gpio number for trst.",
400  .usage = "[trst]",
401  },
402  {
403  .name = "imx_gpio_speed_coeffs",
404  .handler = &imx_gpio_handle_speed_coeffs,
405  .mode = COMMAND_CONFIG,
406  .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
407  .usage = "[SPEED_COEFF SPEED_OFFSET]",
408  },
409  {
410  .name = "imx_gpio_peripheral_base",
411  .handler = &imx_gpio_handle_peripheral_base,
412  .mode = COMMAND_CONFIG,
413  .help = "peripheral base to access GPIOs (0x0209c000 for most IMX).",
414  .usage = "[base]",
415  },
416 
418 };
419 
420 static const char * const imx_gpio_transports[] = { "jtag", "swd", NULL };
421 
422 static struct jtag_interface imx_gpio_interface = {
424  .execute_queue = bitbang_execute_queue,
425 };
426 
428  .name = "imx_gpio",
429  .transports = imx_gpio_transports,
430  .commands = imx_gpio_command_handlers,
431 
432  .init = imx_gpio_init,
433  .quit = imx_gpio_quit,
434  .reset = imx_gpio_reset,
435  .speed = imx_gpio_speed,
436  .khz = imx_gpio_khz,
437  .speed_div = imx_gpio_speed_div,
438 
439  .jtag_ops = &imx_gpio_interface,
440  .swd_ops = &bitbang_swd,
441 };
442 
444 {
445  if (!is_gpio_valid(tck_gpio))
446  return 0;
447  if (!is_gpio_valid(tms_gpio))
448  return 0;
449  if (!is_gpio_valid(tdi_gpio))
450  return 0;
451  if (!is_gpio_valid(tdo_gpio))
452  return 0;
453  return 1;
454 }
455 
456 static bool imx_gpio_swd_mode_possible(void)
457 {
459  return 0;
461  return 0;
462  return 1;
463 }
464 
465 static int imx_gpio_init(void)
466 {
468 
469  LOG_INFO("imx_gpio GPIO JTAG/SWD bitbang driver");
470 
472  LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
473  return ERROR_JTAG_INIT_FAILED;
474  }
475 
477  LOG_ERROR("Require swclk and swdio gpio for SWD mode");
478  return ERROR_JTAG_INIT_FAILED;
479  }
480 
481  dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
482  if (dev_mem_fd < 0) {
483  LOG_ERROR("open: %s", strerror(errno));
484  return ERROR_JTAG_INIT_FAILED;
485  }
486 
487  LOG_INFO("imx_gpio mmap: pagesize: %u, regionsize: %u",
488  (unsigned int) sysconf(_SC_PAGE_SIZE), IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE);
490  PROT_READ | PROT_WRITE,
491  MAP_SHARED, dev_mem_fd, imx_gpio_peri_base);
492 
493  if (pio_base == MAP_FAILED) {
494  LOG_ERROR("mmap: %s", strerror(errno));
495  close(dev_mem_fd);
496  return ERROR_JTAG_INIT_FAILED;
497  }
498 
499  /*
500  * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
501  * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
502  */
503  if (transport_is_jtag()) {
508 
512 
517 
518  if (trst_gpio != -1) {
522  }
523  }
524 
525  if (transport_is_swd()) {
528 
533  }
534 
535  if (srst_gpio != -1) {
539  }
540 
541  LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
542  "tdo %d trst %d srst %d", tck_gpio_mode, tms_gpio_mode,
544 
545  return ERROR_OK;
546 }
547 
548 static int imx_gpio_quit(void)
549 {
550  if (transport_is_jtag()) {
555 
556  if (trst_gpio != -1)
558  }
559 
560  if (transport_is_swd()) {
563  }
564 
565  if (srst_gpio != -1)
567 
568  return ERROR_OK;
569 }
bool transport_is_swd(void)
Returns true if the current debug session is using SWD as its transport.
Definition: adi_v5_swd.c:776
int bitbang_execute_queue(struct jtag_command *cmd_queue)
Definition: bitbang.c:293
const struct swd_driver bitbang_swd
Definition: bitbang.c:614
bb_value_t
Definition: bitbang.h:17
@ BB_LOW
Definition: bitbang.h:18
@ BB_HIGH
Definition: bitbang.h:19
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:443
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
Definition: command.h:141
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:402
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define COMMAND_PARSE_NUMBER(type, in, out)
parses the string in into out as a type, or prints a command error and passes the error code to the c...
Definition: command.h:442
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:253
@ COMMAND_CONFIG
Definition: command.h:41
static int trst_gpio_mode
Definition: imx_gpio.c:104
static int tdo_gpio_mode
Definition: imx_gpio.c:102
static bool imx_gpio_swd_mode_possible(void)
Definition: imx_gpio.c:456
static int srst_gpio
Definition: imx_gpio.c:105
static int tdi_gpio_mode
Definition: imx_gpio.c:100
static int imx_gpio_speed(int speed)
Definition: imx_gpio.c:192
static int imx_gpio_khz(int khz, int *jtag_speed)
Definition: imx_gpio.c:174
static int tdi_gpio
Definition: imx_gpio.c:99
struct adapter_driver imx_gpio_adapter_driver
Definition: imx_gpio.c:427
static const char *const imx_gpio_transports[]
Definition: imx_gpio.c:420
static int swdio_gpio
Definition: imx_gpio.c:109
static struct jtag_interface imx_gpio_interface
Definition: imx_gpio.c:422
static void gpio_mode_input_set(int g)
Definition: imx_gpio.c:45
static int imx_gpio_write(int tck, int tms, int tdi)
Definition: imx_gpio.c:126
static int tms_gpio_mode
Definition: imx_gpio.c:98
static void imx_gpio_swdio_drive(bool is_output)
Definition: imx_gpio.c:161
static int imx_gpio_speed_div(int speed, int *khz)
Definition: imx_gpio.c:186
#define IMX_GPIO_BASE
Definition: imx_gpio.c:19
static int swdio_gpio_mode
Definition: imx_gpio.c:110
static uint32_t imx_gpio_peri_base
Definition: imx_gpio.c:23
static void gpio_mode_output_set(int g)
Definition: imx_gpio.c:50
static int srst_gpio_mode
Definition: imx_gpio.c:106
static int imx_gpio_quit(void)
Definition: imx_gpio.c:548
static int imx_gpio_init(void)
Definition: imx_gpio.c:465
static int is_gpio_valid(int gpio)
Definition: imx_gpio.c:198
static bool gpio_level(int g)
Definition: imx_gpio.c:70
static int imx_gpio_swd_write(int swclk, int swdio)
Definition: imx_gpio.c:138
struct imx_gpio_regs __attribute__((aligned(IMX_GPIO_SIZE)))
static const struct command_registration imx_gpio_command_handlers[]
Definition: imx_gpio.c:331
COMMAND_HANDLER(imx_gpio_handle_jtag_gpionums)
Definition: imx_gpio.c:203
static int tdo_gpio
Definition: imx_gpio.c:101
static void gpio_set(int g)
Definition: imx_gpio.c:60
static int swclk_gpio
Definition: imx_gpio.c:107
static void gpio_clear(int g)
Definition: imx_gpio.c:65
static volatile struct imx_gpio_regs * pio_base
Definition: imx_gpio.c:37
static int trst_gpio
Definition: imx_gpio.c:103
static unsigned int jtag_delay
Definition: imx_gpio.c:119
static int dev_mem_fd
Definition: imx_gpio.c:36
#define IMX_GPIO_SIZE
Definition: imx_gpio.c:20
static int tck_gpio
Definition: imx_gpio.c:95
static int speed_coeff
Definition: imx_gpio.c:117
static int tck_gpio_mode
Definition: imx_gpio.c:96
static int tms_gpio
Definition: imx_gpio.c:97
static int speed_offset
Definition: imx_gpio.c:118
static void gpio_mode_set(int g, int m)
Definition: imx_gpio.c:55
static int swclk_gpio_mode
Definition: imx_gpio.c:108
static struct bitbang_interface imx_gpio_bitbang
Definition: imx_gpio.c:85
static int imx_gpio_swdio_read(void)
Definition: imx_gpio.c:169
#define IMX_GPIO_REGS_COUNT
Definition: imx_gpio.c:21
static int imx_gpio_reset(int trst, int srst)
Definition: imx_gpio.c:150
static bool gpio_mode_get(int g)
Definition: imx_gpio.c:40
static bb_value_t imx_gpio_read(void)
Definition: imx_gpio.c:121
static bool imx_gpio_jtag_mode_possible(void)
Definition: imx_gpio.c:443
#define DEBUG_CAP_TMS_SEQ
Definition: interface.h:187
bool transport_is_jtag(void)
Returns true if the current debug session is using JTAG as its transport.
Definition: jtag/core.c:1833
#define ERROR_JTAG_INIT_FAILED
Definition: jtag.h:552
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_INFO(expr ...)
Definition: log.h:126
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
Represents a driver for a debugging interface.
Definition: interface.h:207
const char *const name
The name of the interface driver.
Definition: interface.h:209
Low level callbacks (for bitbang).
Definition: bitbang.h:30
bb_value_t(* read)(void)
Sample TDO and return the value.
Definition: bitbang.h:32
const char * name
Definition: command.h:235
uint32_t icr2
Definition: imx_gpio.c:30
uint32_t edge_sel
Definition: imx_gpio.c:33
uint32_t psr
Definition: imx_gpio.c:28
uint32_t imr
Definition: imx_gpio.c:31
uint32_t icr1
Definition: imx_gpio.c:29
uint32_t isr
Definition: imx_gpio.c:32
uint32_t gdir
Definition: imx_gpio.c:27
uint32_t dr
Definition: imx_gpio.c:26
Represents a driver for a debugging interface.
Definition: interface.h:182
unsigned int supported
Bit vector listing capabilities exposed by this driver.
Definition: interface.h:186
#define NULL
Definition: usb.h:16