62e276737d64c42084b54f67e7727bc8b5ec51b1
[fw/openocd] / src / jtag / drivers / am335xgpio.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2022 by Steve Marple, stevemarple@googlemail.com        *
5  *                                                                         *
6  *   Based on bcm2835gpio.c and linuxgpiod.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 /*
20  * GPIO register base addresses. Values taken from "AM335x and AMIC110 Sitara
21  * Processors Technical Reference Manual", Chapter 2 Memory Map.
22  */
23 #define AM335XGPIO_NUM_GPIO_PORTS 4
24 #define AM335XGPIO_GPIO0_HW_ADDR 0x44E07000
25 #define AM335XGPIO_GPIO1_HW_ADDR 0x4804C000
26 #define AM335XGPIO_GPIO2_HW_ADDR 0x481AC000
27 #define AM335XGPIO_GPIO3_HW_ADDR 0x481AE000
28
29 /* 32-bit offsets from GPIO port base address. Values taken from "AM335x and
30  * AMIC110 Sitara Processors Technical Reference Manual", Chapter 25
31  * General-Purpose Input/Output.
32  */
33 #define AM335XGPIO_GPIO_OE_OFFSET (0x134 / 4)
34 #define AM335XGPIO_GPIO_DATAIN_OFFSET (0x138 / 4)
35 #define AM335XGPIO_GPIO_DATAOUT_OFFSET (0x13C / 4)  /* DATAOUT register uses 0 for output, 1 for input */
36 #define AM335XGPIO_GPIO_CLEARDATAOUT_OFFSET (0x190 / 4)
37 #define AM335XGPIO_GPIO_SETDATAOUT_OFFSET (0x194 / 4)
38
39 /* GPIOs are integer values; need to map to a port module, and the pin within
40  * that module. GPIOs 0 to 31 map to GPIO0, 32 to 63 to GPIO1 etc. This scheme
41  * matches that used by Linux on the BeagleBone.
42  */
43 #define AM335XGPIO_PORT_NUM(gpio_num) ((gpio_num) / 32)
44 #define AM335XGPIO_BIT_NUM(gpio_num) ((gpio_num) % 32)
45 #define AM335XGPIO_BIT_MASK(gpio_num) BIT(AM335XGPIO_BIT_NUM(gpio_num))
46
47 #define AM335XGPIO_READ_REG(gpio_num, offset) \
48         (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset)))
49
50 #define AM335XGPIO_WRITE_REG(gpio_num, offset, value) \
51         (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset)) = (value))
52
53 #define AM335XGPIO_SET_REG_BITS(gpio_num, offset, bit_mask) \
54         (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset)) |= (bit_mask))
55
56 #define AM335XGPIO_CLEAR_REG_BITS(gpio_num, offset, bit_mask) \
57         (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset)) &= ~(bit_mask))
58
59 enum amx335gpio_gpio_mode {
60         AM335XGPIO_GPIO_MODE_INPUT,
61         AM335XGPIO_GPIO_MODE_OUTPUT, /* To set output mode but not state */
62         AM335XGPIO_GPIO_MODE_OUTPUT_LOW,
63         AM335XGPIO_GPIO_MODE_OUTPUT_HIGH,
64 };
65
66 static const uint32_t am335xgpio_gpio_port_hw_addr[AM335XGPIO_NUM_GPIO_PORTS] = {
67         AM335XGPIO_GPIO0_HW_ADDR,
68         AM335XGPIO_GPIO1_HW_ADDR,
69         AM335XGPIO_GPIO2_HW_ADDR,
70         AM335XGPIO_GPIO3_HW_ADDR,
71 };
72
73 /* Memory-mapped address pointers */
74 static volatile uint32_t *am335xgpio_gpio_port_mmap_addr[AM335XGPIO_NUM_GPIO_PORTS];
75
76 static int dev_mem_fd;
77
78 /* GPIO numbers for each signal. Negative values are invalid */
79 static int tck_gpio = -1;
80 static enum amx335gpio_gpio_mode tck_gpio_mode;
81 static int tms_gpio = -1;
82 static enum amx335gpio_gpio_mode tms_gpio_mode;
83 static int tdi_gpio = -1;
84 static enum amx335gpio_gpio_mode tdi_gpio_mode;
85 static int tdo_gpio = -1;
86 static enum amx335gpio_gpio_mode tdo_gpio_mode;
87 static int trst_gpio = -1;
88 static enum amx335gpio_gpio_mode trst_gpio_mode;
89 static int srst_gpio = -1;
90 static enum amx335gpio_gpio_mode srst_gpio_mode;
91 static int swclk_gpio = -1;
92 static enum amx335gpio_gpio_mode swclk_gpio_mode;
93 static int swdio_gpio = -1;
94 static enum amx335gpio_gpio_mode swdio_gpio_mode;
95 static int swdio_dir_gpio = -1;
96 static enum amx335gpio_gpio_mode swdio_dir_gpio_mode;
97 static int led_gpio = -1;
98 static enum amx335gpio_gpio_mode led_gpio_mode = -1;
99
100 static bool swdio_dir_is_active_high = true; /* Active state means output */
101 static bool led_is_active_high = true;
102
103 /* Transition delay coefficients */
104 static int speed_coeff = 600000;
105 static int speed_offset = 575;
106 static unsigned int jtag_delay;
107
108 static int is_gpio_valid(int gpio_num)
109 {
110         return gpio_num >= 0 && gpio_num < (32 * AM335XGPIO_NUM_GPIO_PORTS);
111 }
112
113 static int get_gpio_value(int gpio_num)
114 {
115         unsigned int shift = AM335XGPIO_BIT_NUM(gpio_num);
116         return (AM335XGPIO_READ_REG(gpio_num, AM335XGPIO_GPIO_DATAIN_OFFSET) >> shift) & 1;
117 }
118
119 static void set_gpio_value(int gpio_num, int value)
120 {
121         if (value)
122                 AM335XGPIO_WRITE_REG(gpio_num, AM335XGPIO_GPIO_SETDATAOUT_OFFSET, AM335XGPIO_BIT_MASK(gpio_num));
123         else
124                 AM335XGPIO_WRITE_REG(gpio_num, AM335XGPIO_GPIO_CLEARDATAOUT_OFFSET, AM335XGPIO_BIT_MASK(gpio_num));
125 }
126
127 static enum amx335gpio_gpio_mode get_gpio_mode(int gpio_num)
128 {
129         if (AM335XGPIO_READ_REG(gpio_num, AM335XGPIO_GPIO_OE_OFFSET) & AM335XGPIO_BIT_MASK(gpio_num)) {
130                 return AM335XGPIO_GPIO_MODE_INPUT;
131         } else {
132                 /* Return output level too so that pin mode can be fully restored */
133                 if (AM335XGPIO_READ_REG(gpio_num, AM335XGPIO_GPIO_DATAOUT_OFFSET) & AM335XGPIO_BIT_MASK(gpio_num))
134                         return AM335XGPIO_GPIO_MODE_OUTPUT_HIGH;
135                 else
136                         return AM335XGPIO_GPIO_MODE_OUTPUT_LOW;
137         }
138 }
139
140 static void set_gpio_mode(int gpio_num, enum amx335gpio_gpio_mode gpio_mode)
141 {
142         if (gpio_mode == AM335XGPIO_GPIO_MODE_INPUT) {
143                 AM335XGPIO_SET_REG_BITS(gpio_num, AM335XGPIO_GPIO_OE_OFFSET, AM335XGPIO_BIT_MASK(gpio_num));
144                 return;
145         }
146
147         if (gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_LOW)
148                 set_gpio_value(gpio_num, 0);
149         if (gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_HIGH)
150                 set_gpio_value(gpio_num, 1);
151
152         if (gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT ||
153                 gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_LOW ||
154                 gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_HIGH) {
155                         AM335XGPIO_CLEAR_REG_BITS(gpio_num, AM335XGPIO_GPIO_OE_OFFSET, AM335XGPIO_BIT_MASK(gpio_num));
156         }
157 }
158
159 static const char *get_gpio_mode_name(enum amx335gpio_gpio_mode gpio_mode)
160 {
161         switch (gpio_mode) {
162         case AM335XGPIO_GPIO_MODE_INPUT:
163                 return "input";
164         case AM335XGPIO_GPIO_MODE_OUTPUT:
165                 return "output";
166         case AM335XGPIO_GPIO_MODE_OUTPUT_LOW:
167                 return "output (low)";
168         case AM335XGPIO_GPIO_MODE_OUTPUT_HIGH:
169                 return "output (high)";
170         default:
171                 return "unknown";
172         }
173 }
174
175 static bb_value_t am335xgpio_read(void)
176 {
177         return get_gpio_value(tdo_gpio) ? BB_HIGH : BB_LOW;
178 }
179
180 static int am335xgpio_write(int tck, int tms, int tdi)
181 {
182         set_gpio_value(tdi_gpio, tdi);
183         set_gpio_value(tms_gpio, tms);
184         set_gpio_value(tck_gpio, tck); /* Write clock last */
185
186         for (unsigned int i = 0; i < jtag_delay; ++i)
187                 asm volatile ("");
188
189         return ERROR_OK;
190 }
191
192 static int am335xgpio_swd_write(int swclk, int swdio)
193 {
194         set_gpio_value(swdio_gpio, swdio);
195         set_gpio_value(swclk_gpio, swclk); /* Write clock last */
196
197         for (unsigned int i = 0; i < jtag_delay; ++i)
198                 asm volatile ("");
199
200         return ERROR_OK;
201 }
202
203 /* (1) assert or (0) deassert reset lines */
204 static int am335xgpio_reset(int trst, int srst)
205 {
206         /* assume active low */
207         if (is_gpio_valid(srst_gpio)) {
208                 if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL)
209                         set_gpio_mode(srst_gpio, srst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_OUTPUT_HIGH);
210                 else
211                         set_gpio_mode(srst_gpio, srst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_INPUT);
212         }
213
214         /* assume active low */
215         if (is_gpio_valid(trst_gpio)) {
216                 if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN)
217                         set_gpio_mode(trst_gpio, trst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_INPUT);
218                 else
219                         set_gpio_mode(trst_gpio, trst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_OUTPUT_HIGH);
220         }
221
222         LOG_DEBUG("am335xgpio_reset(%d, %d), trst_gpio: %d (%s), srst_gpio: %d (%s)",
223                 trst, srst,
224                 trst_gpio, get_gpio_mode_name(get_gpio_mode(trst_gpio)),
225                 srst_gpio, get_gpio_mode_name(get_gpio_mode(srst_gpio)));
226         return ERROR_OK;
227 }
228
229 static void am335xgpio_swdio_drive(bool is_output)
230 {
231         if (is_output) {
232                 set_gpio_value(swdio_dir_gpio, swdio_dir_is_active_high ? 1 : 0);
233                 set_gpio_mode(swdio_gpio, AM335XGPIO_GPIO_MODE_OUTPUT);
234         } else {
235                 set_gpio_mode(swdio_gpio, AM335XGPIO_GPIO_MODE_INPUT);
236                 set_gpio_value(swdio_dir_gpio, swdio_dir_is_active_high ? 0 : 1);
237         }
238 }
239
240 static int am335xgpio_swdio_read(void)
241 {
242         return get_gpio_value(swdio_gpio);
243 }
244
245 static int am335xgpio_blink(int on)
246 {
247         if (is_gpio_valid(led_gpio))
248                 set_gpio_value(led_gpio, (!on ^ led_is_active_high) ? 1 : 0);
249
250         return ERROR_OK;
251 }
252
253 static struct bitbang_interface am335xgpio_bitbang = {
254         .read = am335xgpio_read,
255         .write = am335xgpio_write,
256         .swdio_read = am335xgpio_swdio_read,
257         .swdio_drive = am335xgpio_swdio_drive,
258         .swd_write = am335xgpio_swd_write,
259         .blink = am335xgpio_blink
260 };
261
262 static int am335xgpio_khz(int khz, int *jtag_speed)
263 {
264         if (!khz) {
265                 LOG_DEBUG("RCLK not supported");
266                 return ERROR_FAIL;
267         }
268         *jtag_speed = speed_coeff / khz - speed_offset;
269         if (*jtag_speed < 0)
270                 *jtag_speed = 0;
271         return ERROR_OK;
272 }
273
274 static int am335xgpio_speed_div(int speed, int *khz)
275 {
276         *khz = speed_coeff / (speed + speed_offset);
277         return ERROR_OK;
278 }
279
280 static int am335xgpio_speed(int speed)
281 {
282         jtag_delay = speed;
283         return ERROR_OK;
284 }
285
286 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionums)
287 {
288         if (CMD_ARGC == 4) {
289                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
290                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio);
291                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio);
292                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio);
293         } else if (CMD_ARGC != 0) {
294                 return ERROR_COMMAND_SYNTAX_ERROR;
295         }
296
297         command_print(CMD, "AM335x GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
298                         tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
299         return ERROR_OK;
300 }
301
302 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tck)
303 {
304         if (CMD_ARGC == 1)
305                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
306
307         command_print(CMD, "AM335x GPIO config: tck = %d", tck_gpio);
308         return ERROR_OK;
309 }
310
311 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tms)
312 {
313         if (CMD_ARGC == 1)
314                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio);
315
316         command_print(CMD, "AM335x GPIO config: tms = %d", tms_gpio);
317         return ERROR_OK;
318 }
319
320 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tdo)
321 {
322         if (CMD_ARGC == 1)
323                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio);
324
325         command_print(CMD, "AM335x GPIO config: tdo = %d", tdo_gpio);
326         return ERROR_OK;
327 }
328
329 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tdi)
330 {
331         if (CMD_ARGC == 1)
332                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio);
333
334         command_print(CMD, "AM335x GPIO config: tdi = %d", tdi_gpio);
335         return ERROR_OK;
336 }
337
338 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_srst)
339 {
340         if (CMD_ARGC == 1)
341                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio);
342
343         command_print(CMD, "AM335x GPIO config: srst = %d", srst_gpio);
344         return ERROR_OK;
345 }
346
347 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_trst)
348 {
349         if (CMD_ARGC == 1)
350                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio);
351
352         command_print(CMD, "AM335x GPIO config: trst = %d", trst_gpio);
353         return ERROR_OK;
354 }
355
356 COMMAND_HANDLER(am335xgpio_handle_swd_gpionums)
357 {
358         if (CMD_ARGC == 2) {
359                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
360                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio);
361         } else if (CMD_ARGC != 0) {
362                 return ERROR_COMMAND_SYNTAX_ERROR;
363         }
364
365         command_print(CMD, "AM335x GPIO config: swclk = %d, swdio = %d", swclk_gpio, swdio_gpio);
366
367         return ERROR_OK;
368 }
369
370 COMMAND_HANDLER(am335xgpio_handle_swd_gpionum_swclk)
371 {
372         if (CMD_ARGC == 1)
373                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
374
375         command_print(CMD, "AM335x GPIO config: swclk = %d", swclk_gpio);
376         return ERROR_OK;
377 }
378
379 COMMAND_HANDLER(am335xgpio_handle_swd_gpionum_swdio)
380 {
381         if (CMD_ARGC == 1)
382                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio);
383
384         command_print(CMD, "AM335x GPIO config: swdio = %d", swdio_gpio);
385         return ERROR_OK;
386 }
387
388 COMMAND_HANDLER(am335xgpio_handle_swd_gpionum_swdio_dir)
389 {
390         if (CMD_ARGC == 1)
391                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_dir_gpio);
392
393         command_print(CMD, "AM335x GPIO config: swdio_dir = %d", swdio_dir_gpio);
394         return ERROR_OK;
395 }
396
397 COMMAND_HANDLER(am335xgpio_handle_swd_dir_output_state)
398 {
399         if (CMD_ARGC == 1)
400                 COMMAND_PARSE_BOOL(CMD_ARGV[0], swdio_dir_is_active_high, "high", "low");
401
402         command_print(CMD, "AM335x GPIO config: swdio_dir_output_state = %s", swdio_dir_is_active_high ? "high" : "low");
403         return ERROR_OK;
404 }
405
406 COMMAND_HANDLER(am335xgpio_handle_gpionum_led)
407 {
408         if (CMD_ARGC == 1)
409                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], led_gpio);
410
411         command_print(CMD, "AM335x GPIO config: led = %d", led_gpio);
412         return ERROR_OK;
413 }
414
415 COMMAND_HANDLER(am335xgpio_handle_led_on_state)
416 {
417         if (CMD_ARGC == 1)
418                 COMMAND_PARSE_BOOL(CMD_ARGV[0], led_is_active_high, "high", "low");
419
420         command_print(CMD, "AM335x GPIO config: led_on_state = %s", led_is_active_high ? "high" : "low");
421         return ERROR_OK;
422 }
423
424 COMMAND_HANDLER(am335xgpio_handle_speed_coeffs)
425 {
426         if (CMD_ARGC == 2) {
427                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff);
428                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset);
429         }
430
431         command_print(CMD, "AM335x GPIO config: speed_coeffs = %d, speed_offset = %d",
432                                   speed_coeff, speed_offset);
433         return ERROR_OK;
434 }
435
436 static const struct command_registration am335xgpio_subcommand_handlers[] = {
437         {
438                 .name = "jtag_nums",
439                 .handler = am335xgpio_handle_jtag_gpionums,
440                 .mode = COMMAND_CONFIG,
441                 .help = "gpio numbers for tck, tms, tdi, tdo (in that order).",
442                 .usage = "[tck tms tdi tdo]",
443         },
444         {
445                 .name = "tck_num",
446                 .handler = am335xgpio_handle_jtag_gpionum_tck,
447                 .mode = COMMAND_CONFIG,
448                 .help = "gpio number for tck.",
449                 .usage = "[tck]",
450         },
451         {
452                 .name = "tms_num",
453                 .handler = am335xgpio_handle_jtag_gpionum_tms,
454                 .mode = COMMAND_CONFIG,
455                 .help = "gpio number for tms.",
456                 .usage = "[tms]",
457         },
458         {
459                 .name = "tdo_num",
460                 .handler = am335xgpio_handle_jtag_gpionum_tdo,
461                 .mode = COMMAND_CONFIG,
462                 .help = "gpio number for tdo.",
463                 .usage = "[tdo]",
464         },
465         {
466                 .name = "tdi_num",
467                 .handler = am335xgpio_handle_jtag_gpionum_tdi,
468                 .mode = COMMAND_CONFIG,
469                 .help = "gpio number for tdi.",
470                 .usage = "[tdi]",
471         },
472         {
473                 .name = "swd_nums",
474                 .handler = am335xgpio_handle_swd_gpionums,
475                 .mode = COMMAND_CONFIG,
476                 .help = "gpio numbers for swclk, swdio (in that order).",
477                 .usage = "[swclk swdio]",
478         },
479         {
480                 .name = "swclk_num",
481                 .handler = am335xgpio_handle_swd_gpionum_swclk,
482                 .mode = COMMAND_CONFIG,
483                 .help = "gpio number for swclk.",
484                 .usage = "[swclk]",
485         },
486         {
487                 .name = "swdio_num",
488                 .handler = am335xgpio_handle_swd_gpionum_swdio,
489                 .mode = COMMAND_CONFIG,
490                 .help = "gpio number for swdio.",
491                 .usage = "[swdio]",
492         },
493         {
494                 .name = "swdio_dir_num",
495                 .handler = am335xgpio_handle_swd_gpionum_swdio_dir,
496                 .mode = COMMAND_CONFIG,
497                 .help = "gpio number for swdio direction control pin.",
498                 .usage = "[swdio_dir]",
499         },
500         {
501                 .name = "swdio_dir_output_state",
502                 .handler = am335xgpio_handle_swd_dir_output_state,
503                 .mode = COMMAND_CONFIG,
504                 .help = "required state for swdio_dir pin to select SWDIO buffer to be output.",
505                 .usage = "['off'|'on']",
506         },
507         {
508                 .name = "srst_num",
509                 .handler = am335xgpio_handle_jtag_gpionum_srst,
510                 .mode = COMMAND_CONFIG,
511                 .help = "gpio number for srst.",
512                 .usage = "[srst]",
513         },
514         {
515                 .name = "trst_num",
516                 .handler = am335xgpio_handle_jtag_gpionum_trst,
517                 .mode = COMMAND_CONFIG,
518                 .help = "gpio number for trst.",
519                 .usage = "[trst]",
520         },
521         {
522                 .name = "led_num",
523                 .handler = am335xgpio_handle_gpionum_led,
524                 .mode = COMMAND_CONFIG,
525                 .help = "gpio number for led.",
526                 .usage = "[led]",
527         },
528         {
529                 .name = "led_on_state",
530                 .handler = am335xgpio_handle_led_on_state,
531                 .mode = COMMAND_CONFIG,
532                 .help = "required state for led pin to turn on LED.",
533                 .usage = "['off'|'on']",
534         },
535         {
536                 .name = "speed_coeffs",
537                 .handler = am335xgpio_handle_speed_coeffs,
538                 .mode = COMMAND_CONFIG,
539                 .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
540                 .usage = "[SPEED_COEFF SPEED_OFFSET]",
541         },
542         COMMAND_REGISTRATION_DONE
543 };
544
545 static const struct command_registration am335xgpio_command_handlers[] = {
546         {
547                 .name = "am335xgpio",
548                 .mode = COMMAND_ANY,
549                 .help = "perform am335xgpio management",
550                 .chain = am335xgpio_subcommand_handlers,
551                 .usage = "",
552         },
553         COMMAND_REGISTRATION_DONE
554 };
555
556 static const char * const am335xgpio_transports[] = { "jtag", "swd", NULL };
557
558 static struct jtag_interface am335xgpio_interface = {
559         .supported = DEBUG_CAP_TMS_SEQ,
560         .execute_queue = bitbang_execute_queue,
561 };
562
563 static bool am335xgpio_jtag_mode_possible(void)
564 {
565         if (!is_gpio_valid(tck_gpio))
566                 return false;
567         if (!is_gpio_valid(tms_gpio))
568                 return false;
569         if (!is_gpio_valid(tdi_gpio))
570                 return false;
571         if (!is_gpio_valid(tdo_gpio))
572                 return false;
573         return true;
574 }
575
576 static bool am335xgpio_swd_mode_possible(void)
577 {
578         if (!is_gpio_valid(swclk_gpio))
579                 return false;
580         if (!is_gpio_valid(swdio_gpio))
581                 return false;
582         return true;
583 }
584
585 static int am335xgpio_init(void)
586 {
587         bitbang_interface = &am335xgpio_bitbang;
588
589         LOG_INFO("AM335x GPIO JTAG/SWD bitbang driver");
590
591         if (transport_is_jtag() && !am335xgpio_jtag_mode_possible()) {
592                 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
593                 return ERROR_JTAG_INIT_FAILED;
594         }
595
596         if (transport_is_swd() && !am335xgpio_swd_mode_possible()) {
597                 LOG_ERROR("Require swclk and swdio gpio for SWD mode");
598                 return ERROR_JTAG_INIT_FAILED;
599         }
600
601         dev_mem_fd = open("/dev/gpiomem", O_RDWR | O_SYNC);
602         if (dev_mem_fd < 0) {
603                 LOG_DEBUG("Cannot open /dev/gpiomem, fallback to /dev/mem");
604                 dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
605         }
606         if (dev_mem_fd < 0) {
607                 LOG_ERROR("open: %s", strerror(errno));
608                 return ERROR_JTAG_INIT_FAILED;
609         }
610
611         for (unsigned int i = 0; i < AM335XGPIO_NUM_GPIO_PORTS; ++i) {
612                 am335xgpio_gpio_port_mmap_addr[i] = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
613                                 MAP_SHARED, dev_mem_fd, am335xgpio_gpio_port_hw_addr[i]);
614
615                 if (am335xgpio_gpio_port_mmap_addr[i] == MAP_FAILED) {
616                         LOG_ERROR("mmap: %s", strerror(errno));
617                         close(dev_mem_fd);
618                         return ERROR_JTAG_INIT_FAILED;
619                 }
620         }
621
622         /*
623          * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST as outputs.
624          * Drive TDI and TCK low, and TMS high.
625          */
626         if (transport_is_jtag()) {
627                 tdo_gpio_mode = get_gpio_mode(tdo_gpio);
628                 tdi_gpio_mode = get_gpio_mode(tdi_gpio);
629                 tck_gpio_mode = get_gpio_mode(tck_gpio);
630                 tms_gpio_mode = get_gpio_mode(tms_gpio);
631                 LOG_DEBUG("saved GPIO mode for tdo (GPIO #%d): %s", tdo_gpio, get_gpio_mode_name(tdo_gpio_mode));
632                 LOG_DEBUG("saved GPIO mode for tdi (GPIO #%d): %s", tdi_gpio, get_gpio_mode_name(tdi_gpio_mode));
633                 LOG_DEBUG("saved GPIO mode for tck (GPIO #%d): %s", tck_gpio, get_gpio_mode_name(tck_gpio_mode));
634                 LOG_DEBUG("saved GPIO mode for tms (GPIO #%d): %s", tms_gpio, get_gpio_mode_name(tms_gpio_mode));
635
636                 set_gpio_mode(tdo_gpio, AM335XGPIO_GPIO_MODE_INPUT);
637                 set_gpio_mode(tdi_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW);
638                 set_gpio_mode(tms_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_HIGH);
639                 set_gpio_mode(tck_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW);
640
641                 if (is_gpio_valid(trst_gpio)) {
642                         trst_gpio_mode = get_gpio_mode(trst_gpio);
643                         LOG_DEBUG("saved GPIO mode for trst (GPIO #%d): %s", trst_gpio, get_gpio_mode_name(trst_gpio_mode));
644                 }
645         }
646
647         if (transport_is_swd()) {
648                 swclk_gpio_mode = get_gpio_mode(swclk_gpio);
649                 swdio_gpio_mode = get_gpio_mode(swdio_gpio);
650                 LOG_DEBUG("saved GPIO mode for swclk (GPIO #%d): %s", swclk_gpio, get_gpio_mode_name(swclk_gpio_mode));
651                 LOG_DEBUG("saved GPIO mode for swdio (GPIO #%d): %s", swdio_gpio, get_gpio_mode_name(swdio_gpio_mode));
652                 if (is_gpio_valid(swdio_dir_gpio)) {
653                         swdio_dir_gpio_mode = get_gpio_mode(swdio_dir_gpio);
654                         LOG_DEBUG("saved GPIO mode for swdio_dir (GPIO #%d): %s",
655                                         swdio_dir_gpio, get_gpio_mode_name(swdio_dir_gpio_mode));
656                         set_gpio_mode(swdio_dir_gpio,
657                                         swdio_dir_is_active_high ? AM335XGPIO_GPIO_MODE_OUTPUT_HIGH : AM335XGPIO_GPIO_MODE_OUTPUT_LOW);
658
659                 }
660                 set_gpio_mode(swdio_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW);
661                 set_gpio_mode(swclk_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW);
662         }
663
664         if (is_gpio_valid(srst_gpio)) {
665                 srst_gpio_mode = get_gpio_mode(srst_gpio);
666                 LOG_DEBUG("saved GPIO mode for srst (GPIO #%d): %s", srst_gpio, get_gpio_mode_name(srst_gpio_mode));
667         }
668
669         if (is_gpio_valid(led_gpio)) {
670                 led_gpio_mode = get_gpio_mode(led_gpio);
671                 LOG_DEBUG("saved GPIO mode for led (GPIO #%d): %s", led_gpio, get_gpio_mode_name(led_gpio_mode));
672                 set_gpio_mode(led_gpio,
673                                 led_is_active_high ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_OUTPUT_HIGH);
674         }
675
676         /* Set GPIO modes for TRST and SRST and make both inactive */
677         am335xgpio_reset(0, 0);
678         return ERROR_OK;
679 }
680
681 static int am335xgpio_quit(void)
682 {
683         if (transport_is_jtag()) {
684                 set_gpio_mode(tdo_gpio, tdo_gpio_mode);
685                 set_gpio_mode(tdi_gpio, tdi_gpio_mode);
686                 set_gpio_mode(tck_gpio, tck_gpio_mode);
687                 set_gpio_mode(tms_gpio, tms_gpio_mode);
688                 if (is_gpio_valid(trst_gpio))
689                         set_gpio_mode(trst_gpio, trst_gpio_mode);
690         }
691
692         if (transport_is_swd()) {
693                 set_gpio_mode(swclk_gpio, swclk_gpio_mode);
694                 set_gpio_mode(swdio_gpio, swdio_gpio_mode);
695                 if (is_gpio_valid(swdio_dir_gpio))
696                         set_gpio_mode(swdio_dir_gpio, swdio_dir_gpio_mode);
697         }
698
699         if (is_gpio_valid(srst_gpio))
700                 set_gpio_mode(srst_gpio, srst_gpio_mode);
701
702         if (is_gpio_valid(led_gpio))
703                 set_gpio_mode(led_gpio, led_gpio_mode);
704
705         return ERROR_OK;
706 }
707
708 struct adapter_driver am335xgpio_adapter_driver = {
709         .name = "am335xgpio",
710         .transports = am335xgpio_transports,
711         .commands = am335xgpio_command_handlers,
712
713         .init = am335xgpio_init,
714         .quit = am335xgpio_quit,
715         .reset = am335xgpio_reset,
716         .speed = am335xgpio_speed,
717         .khz = am335xgpio_khz,
718         .speed_div = am335xgpio_speed_div,
719
720         .jtag_ops = &am335xgpio_interface,
721         .swd_ops = &bitbang_swd,
722 };