OpenOCD
am335xgpio.c
Go to the documentation of this file.
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/adapter.h>
14 #include <jtag/interface.h>
15 #include <transport/transport.h>
16 #include "bitbang.h"
17 
18 #include <sys/mman.h>
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_PER_CHIP 32
24 #define AM335XGPIO_NUM_GPIO_CHIPS 4
25 #define AM335XGPIO_GPIO0_HW_ADDR 0x44E07000
26 #define AM335XGPIO_GPIO1_HW_ADDR 0x4804C000
27 #define AM335XGPIO_GPIO2_HW_ADDR 0x481AC000
28 #define AM335XGPIO_GPIO3_HW_ADDR 0x481AE000
29 
30 /* 32-bit offsets from GPIO chip base address. Values taken from "AM335x and
31  * AMIC110 Sitara Processors Technical Reference Manual", Chapter 25
32  * General-Purpose Input/Output.
33  */
34 #define AM335XGPIO_GPIO_OE_OFFSET (0x134 / 4)
35 #define AM335XGPIO_GPIO_DATAIN_OFFSET (0x138 / 4)
36 #define AM335XGPIO_GPIO_DATAOUT_OFFSET (0x13C / 4) /* DATAOUT register uses 0 for output, 1 for input */
37 #define AM335XGPIO_GPIO_CLEARDATAOUT_OFFSET (0x190 / 4)
38 #define AM335XGPIO_GPIO_SETDATAOUT_OFFSET (0x194 / 4)
39 
40 #define AM335XGPIO_READ_REG(chip_num, offset) \
41  (*(am335xgpio_gpio_chip_mmap_addr[(chip_num)] + (offset)))
42 
43 #define AM335XGPIO_WRITE_REG(chip_num, offset, value) \
44  (*(am335xgpio_gpio_chip_mmap_addr[(chip_num)] + (offset)) = (value))
45 
46 #define AM335XGPIO_SET_REG_BITS(chip_num, offset, bit_mask) \
47  (*(am335xgpio_gpio_chip_mmap_addr[(chip_num)] + (offset)) |= (bit_mask))
48 
49 #define AM335XGPIO_CLEAR_REG_BITS(chip_num, offset, bit_mask) \
50  (*(am335xgpio_gpio_chip_mmap_addr[(chip_num)] + (offset)) &= ~(bit_mask))
51 
52 #define AM335XGPIO_SET_INPUT(gpio_config) \
53  AM335XGPIO_SET_REG_BITS((gpio_config)->chip_num, AM335XGPIO_GPIO_OE_OFFSET, BIT((gpio_config)->gpio_num))
54 #define AM335XGPIO_SET_OUTPUT(gpio_config) \
55  AM335XGPIO_CLEAR_REG_BITS((gpio_config)->chip_num, AM335XGPIO_GPIO_OE_OFFSET, BIT((gpio_config)->gpio_num))
56 #define AM335XGPIO_SET_HIGH(gpio_config) \
57  AM335XGPIO_WRITE_REG((gpio_config)->chip_num, AM335XGPIO_GPIO_SETDATAOUT_OFFSET, BIT((gpio_config)->gpio_num))
58 #define AM335XGPIO_SET_LOW(gpio_config) \
59  AM335XGPIO_WRITE_REG((gpio_config)->chip_num, AM335XGPIO_GPIO_CLEARDATAOUT_OFFSET, BIT((gpio_config)->gpio_num))
60 
65 };
66 
72 };
73 
74 /* Memory-mapped address pointers */
76 
77 static int dev_mem_fd;
79 
80 /* Transition delay coefficients */
81 static int speed_coeff = 600000;
82 static int speed_offset = 575;
83 static unsigned int jtag_delay;
84 
86 
87 static bool is_gpio_config_valid(const struct adapter_gpio_config *gpio_config)
88 {
89  return gpio_config->chip_num >= 0
90  && gpio_config->chip_num < AM335XGPIO_NUM_GPIO_CHIPS
91  && gpio_config->gpio_num >= 0
92  && gpio_config->gpio_num < AM335XGPIO_NUM_GPIO_PER_CHIP;
93 }
94 
95 static int get_gpio_value(const struct adapter_gpio_config *gpio_config)
96 {
97  unsigned int shift = gpio_config->gpio_num;
98  uint32_t value = AM335XGPIO_READ_REG(gpio_config->chip_num, AM335XGPIO_GPIO_DATAIN_OFFSET);
99  value = (value >> shift) & 1;
100  return value ^ (gpio_config->active_low ? 1 : 0);
101 }
102 
103 static void set_gpio_value(const struct adapter_gpio_config *gpio_config, int value)
104 {
105  value = value ^ (gpio_config->active_low ? 1 : 0);
106  switch (gpio_config->drive) {
108  if (value)
109  AM335XGPIO_SET_HIGH(gpio_config);
110  else
111  AM335XGPIO_SET_LOW(gpio_config);
112  /* For performance reasons assume the GPIO is already set as an output
113  * and therefore the call can be omitted here.
114  */
115  break;
117  if (value) {
118  AM335XGPIO_SET_INPUT(gpio_config);
119  } else {
120  AM335XGPIO_SET_LOW(gpio_config);
121  AM335XGPIO_SET_OUTPUT(gpio_config);
122  }
123  break;
125  if (value) {
126  AM335XGPIO_SET_HIGH(gpio_config);
127  AM335XGPIO_SET_OUTPUT(gpio_config);
128  } else {
129  AM335XGPIO_SET_INPUT(gpio_config);
130  }
131  break;
132  }
133 }
134 
135 static enum amx335gpio_initial_gpio_mode get_gpio_mode(const struct adapter_gpio_config *gpio_config)
136 {
137  if (AM335XGPIO_READ_REG(gpio_config->chip_num, AM335XGPIO_GPIO_OE_OFFSET) & BIT(gpio_config->gpio_num))
139 
140  /* Return output level too so that pin mode can be fully restored */
141  if (AM335XGPIO_READ_REG(gpio_config->chip_num, AM335XGPIO_GPIO_DATAOUT_OFFSET) & BIT(gpio_config->gpio_num))
144 }
145 
146 static const char *get_gpio_mode_name(enum amx335gpio_initial_gpio_mode gpio_mode)
147 {
148  switch (gpio_mode) {
150  return "input";
152  return "output (low)";
154  return "output (high)";
155  }
156  return "unknown";
157 }
158 
160 {
162  return;
163 
165  LOG_DEBUG("saved GPIO mode for %s (GPIO %d %d): %s",
168 
170  LOG_WARNING("am335xgpio does not support pull-up or pull-down settings (signal %s)",
171  adapter_gpio_get_name(idx));
172  }
173 
174  switch (adapter_gpio_config[idx].init_state) {
177  break;
180  break;
183  break;
184  }
185 
186  /* Direction for non push-pull is already set by set_gpio_value() */
189 }
190 
192 {
194  switch (initial_gpio_mode[idx]) {
197  break;
201  break;
205  break;
206  }
207  }
208 }
209 
211 {
213 }
214 
215 static int am335xgpio_write(int tck, int tms, int tdi)
216 {
219  set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TCK], tck); /* Write clock last */
220 
221  for (unsigned int i = 0; i < jtag_delay; ++i)
222  asm volatile ("");
223 
224  return ERROR_OK;
225 }
226 
227 static int am335xgpio_swd_write(int swclk, int swdio)
228 {
230  set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK], swclk); /* Write clock last */
231 
232  for (unsigned int i = 0; i < jtag_delay; ++i)
233  asm volatile ("");
234 
235  return ERROR_OK;
236 }
237 
238 /* (1) assert or (0) deassert reset lines */
239 static int am335xgpio_reset(int trst, int srst)
240 {
241  /* As the "adapter reset_config" command keeps the srst and trst gpio drive
242  * mode settings in sync we can use our standard set_gpio_value() function
243  * that honours drive mode and active low.
244  */
247 
250 
251  LOG_DEBUG("am335xgpio_reset(%d, %d), trst_gpio: %d %d, srst_gpio: %d %d",
252  trst, srst,
255  return ERROR_OK;
256 }
257 
258 static void am335xgpio_swdio_drive(bool is_output)
259 {
260  if (is_output) {
264  } else {
268  }
269 }
270 
271 static int am335xgpio_swdio_read(void)
272 {
274 }
275 
276 static int am335xgpio_blink(int on)
277 {
280 
281  return ERROR_OK;
282 }
283 
284 static struct bitbang_interface am335xgpio_bitbang = {
286  .write = am335xgpio_write,
287  .swdio_read = am335xgpio_swdio_read,
288  .swdio_drive = am335xgpio_swdio_drive,
289  .swd_write = am335xgpio_swd_write,
290  .blink = am335xgpio_blink
291 };
292 
293 static int am335xgpio_khz(int khz, int *jtag_speed)
294 {
295  if (!khz) {
296  LOG_DEBUG("RCLK not supported");
297  return ERROR_FAIL;
298  }
299  *jtag_speed = speed_coeff / khz - speed_offset;
300  if (*jtag_speed < 0)
301  *jtag_speed = 0;
302  return ERROR_OK;
303 }
304 
305 static int am335xgpio_speed_div(int speed, int *khz)
306 {
307  *khz = speed_coeff / (speed + speed_offset);
308  return ERROR_OK;
309 }
310 
311 static int am335xgpio_speed(int speed)
312 {
313  jtag_delay = speed;
314  return ERROR_OK;
315 }
316 
317 COMMAND_HANDLER(am335xgpio_handle_speed_coeffs)
318 {
319  if (CMD_ARGC == 2) {
322  }
323 
324  command_print(CMD, "AM335x GPIO config: speed_coeffs = %d, speed_offset = %d",
326  return ERROR_OK;
327 }
328 
330  {
331  .name = "speed_coeffs",
332  .handler = am335xgpio_handle_speed_coeffs,
333  .mode = COMMAND_CONFIG,
334  .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
335  .usage = "[SPEED_COEFF SPEED_OFFSET]",
336  },
338 };
339 
340 static const struct command_registration am335xgpio_command_handlers[] = {
341  {
342  .name = "am335xgpio",
343  .mode = COMMAND_ANY,
344  .help = "perform am335xgpio management",
346  .usage = "",
347  },
349 };
350 
351 static const char * const am335xgpio_transports[] = { "jtag", "swd", NULL };
352 
353 static struct jtag_interface am335xgpio_interface = {
355  .execute_queue = bitbang_execute_queue,
356 };
357 
359 {
361  return false;
363  return false;
365  return false;
367  return false;
368  return true;
369 }
370 
372 {
374  return false;
376  return false;
377  return true;
378 }
379 
380 static void am335xgpio_munmap(void)
381 {
382  for (unsigned int i = 0; i < AM335XGPIO_NUM_GPIO_CHIPS && am335xgpio_gpio_chip_mmap_addr[i] != MAP_FAILED; ++i)
383  if (munmap((void *)am335xgpio_gpio_chip_mmap_addr[i], sysconf(_SC_PAGE_SIZE)) < 0)
384  LOG_ERROR("Cannot unmap GPIO memory for chip %d: %s", i, strerror(errno));
385 }
386 
387 static int am335xgpio_init(void)
388 {
389  LOG_INFO("AM335x GPIO JTAG/SWD bitbang driver");
390 
393 
395  LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
396  return ERROR_JTAG_INIT_FAILED;
397  }
398 
400  LOG_ERROR("Require swclk and swdio gpio for SWD mode");
401  return ERROR_JTAG_INIT_FAILED;
402  }
403 
404  dev_mem_fd = open("/dev/gpiomem", O_RDWR | O_SYNC);
405  if (dev_mem_fd < 0) {
406  LOG_DEBUG("Cannot open /dev/gpiomem, fallback to /dev/mem");
407  dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
408  }
409  if (dev_mem_fd < 0) {
410  LOG_ERROR("open: %s", strerror(errno));
411  return ERROR_JTAG_INIT_FAILED;
412  }
413 
414  for (unsigned int i = 0; i < AM335XGPIO_NUM_GPIO_CHIPS; ++i) {
415  am335xgpio_gpio_chip_mmap_addr[i] = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
416  MAP_SHARED, dev_mem_fd, am335xgpio_gpio_chip_hw_addr[i]);
417 
418  if (am335xgpio_gpio_chip_mmap_addr[i] == MAP_FAILED) {
419  LOG_ERROR("mmap: %s", strerror(errno));
421  close(dev_mem_fd);
422  return ERROR_JTAG_INIT_FAILED;
423  }
424  }
425  close(dev_mem_fd);
426 
427  /* Configure JTAG/SWD signals. Default directions and initial states are handled
428  * by adapter.c and "adapter gpio" command.
429  */
430  if (transport_is_jtag()) {
436  }
437 
438  if (transport_is_swd()) {
439  /* swdio and its buffer should be initialized in the order that prevents
440  * two outputs from being connected together. This will occur if the
441  * swdio GPIO of the AM335x is configured as an output while its
442  * external buffer is configured to send the swdio signal from the
443  * target to the AM335x.
444  */
448  } else {
451  }
452 
454  }
455 
458 
459  return ERROR_OK;
460 }
461 
462 static int am335xgpio_quit(void)
463 {
464  if (transport_is_jtag()) {
470  }
471 
472  if (transport_is_swd()) {
473  /* Restore swdio/swdio_dir to their initial modes, even if that means
474  * connecting two outputs. Begin by making swdio an input so that the
475  * current and final states of swdio and swdio_dir do not have to be
476  * considered to calculate the safe restoration order.
477  */
481 
483  }
484 
487 
489 
490  return ERROR_OK;
491 }
492 
494  .name = "am335xgpio",
495  .transports = am335xgpio_transports,
496  .commands = am335xgpio_command_handlers,
497 
498  .init = am335xgpio_init,
499  .quit = am335xgpio_quit,
500  .reset = am335xgpio_reset,
501  .speed = am335xgpio_speed,
502  .khz = am335xgpio_khz,
503  .speed_div = am335xgpio_speed_div,
504 
505  .jtag_ops = &am335xgpio_interface,
506  .swd_ops = &bitbang_swd,
507 };
const struct adapter_gpio_config * adapter_gpio_get_config(void)
Retrieves gpio configuration set with command "adapter gpio <signal_name>".
Definition: adapter.c:1223
const char * adapter_gpio_get_name(enum adapter_gpio_config_index idx)
Retrieves gpio name.
Definition: adapter.c:1217
@ ADAPTER_GPIO_INIT_STATE_ACTIVE
Definition: adapter.h:31
@ ADAPTER_GPIO_INIT_STATE_INPUT
Definition: adapter.h:32
@ ADAPTER_GPIO_INIT_STATE_INACTIVE
Definition: adapter.h:30
adapter_gpio_config_index
Adapter GPIO.
Definition: adapter.h:43
@ ADAPTER_GPIO_IDX_LED
Definition: adapter.h:53
@ ADAPTER_GPIO_IDX_NUM
Definition: adapter.h:54
@ ADAPTER_GPIO_IDX_SWCLK
Definition: adapter.h:51
@ ADAPTER_GPIO_IDX_SWDIO_DIR
Definition: adapter.h:50
@ ADAPTER_GPIO_IDX_SRST
Definition: adapter.h:52
@ ADAPTER_GPIO_IDX_TRST
Definition: adapter.h:48
@ ADAPTER_GPIO_IDX_TDI
Definition: adapter.h:45
@ ADAPTER_GPIO_IDX_TMS
Definition: adapter.h:46
@ ADAPTER_GPIO_IDX_TCK
Definition: adapter.h:47
@ ADAPTER_GPIO_IDX_TDO
Definition: adapter.h:44
@ ADAPTER_GPIO_IDX_SWDIO
Definition: adapter.h:49
@ ADAPTER_GPIO_PULL_NONE
Definition: adapter.h:37
@ ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE
Definition: adapter.h:18
@ ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN
Definition: adapter.h:17
@ ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL
Definition: adapter.h:16
bool transport_is_swd(void)
Returns true if the current debug session is using SWD as its transport.
Definition: adi_v5_swd.c:728
static int am335xgpio_swdio_read(void)
Definition: am335xgpio.c:271
static int am335xgpio_quit(void)
Definition: am335xgpio.c:462
static const struct command_registration am335xgpio_command_handlers[]
Definition: am335xgpio.c:340
static const char * get_gpio_mode_name(enum amx335gpio_initial_gpio_mode gpio_mode)
Definition: am335xgpio.c:146
#define AM335XGPIO_SET_OUTPUT(gpio_config)
Definition: am335xgpio.c:54
static int am335xgpio_write(int tck, int tms, int tdi)
Definition: am335xgpio.c:215
#define AM335XGPIO_SET_HIGH(gpio_config)
Definition: am335xgpio.c:56
#define AM335XGPIO_NUM_GPIO_PER_CHIP
Definition: am335xgpio.c:23
static void restore_gpio(enum adapter_gpio_config_index idx)
Definition: am335xgpio.c:191
static void am335xgpio_munmap(void)
Definition: am335xgpio.c:380
static int am335xgpio_speed_div(int speed, int *khz)
Definition: am335xgpio.c:305
#define AM335XGPIO_GPIO_DATAOUT_OFFSET
Definition: am335xgpio.c:36
static bool am335xgpio_swd_mode_possible(void)
Definition: am335xgpio.c:371
#define AM335XGPIO_GPIO3_HW_ADDR
Definition: am335xgpio.c:28
static int am335xgpio_init(void)
Definition: am335xgpio.c:387
#define AM335XGPIO_GPIO2_HW_ADDR
Definition: am335xgpio.c:27
#define AM335XGPIO_GPIO_OE_OFFSET
Definition: am335xgpio.c:34
static const uint32_t am335xgpio_gpio_chip_hw_addr[AM335XGPIO_NUM_GPIO_CHIPS]
Definition: am335xgpio.c:67
static int am335xgpio_speed(int speed)
Definition: am335xgpio.c:311
#define AM335XGPIO_SET_INPUT(gpio_config)
Definition: am335xgpio.c:52
static volatile uint32_t * am335xgpio_gpio_chip_mmap_addr[AM335XGPIO_NUM_GPIO_CHIPS]
Definition: am335xgpio.c:75
static unsigned int jtag_delay
Definition: am335xgpio.c:83
#define AM335XGPIO_READ_REG(chip_num, offset)
Definition: am335xgpio.c:40
static int am335xgpio_khz(int khz, int *jtag_speed)
Definition: am335xgpio.c:293
static struct jtag_interface am335xgpio_interface
Definition: am335xgpio.c:353
struct adapter_driver am335xgpio_adapter_driver
Definition: am335xgpio.c:493
static int dev_mem_fd
Definition: am335xgpio.c:77
static const struct command_registration am335xgpio_subcommand_handlers[]
Definition: am335xgpio.c:329
amx335gpio_initial_gpio_mode
Definition: am335xgpio.c:61
@ AM335XGPIO_GPIO_MODE_OUTPUT_LOW
Definition: am335xgpio.c:63
@ AM335XGPIO_GPIO_MODE_OUTPUT_HIGH
Definition: am335xgpio.c:64
@ AM335XGPIO_GPIO_MODE_INPUT
Definition: am335xgpio.c:62
static int speed_coeff
Definition: am335xgpio.c:81
#define AM335XGPIO_NUM_GPIO_CHIPS
Definition: am335xgpio.c:24
static const struct adapter_gpio_config * adapter_gpio_config
Definition: am335xgpio.c:85
static int am335xgpio_swd_write(int swclk, int swdio)
Definition: am335xgpio.c:227
COMMAND_HANDLER(am335xgpio_handle_speed_coeffs)
Definition: am335xgpio.c:317
static void set_gpio_value(const struct adapter_gpio_config *gpio_config, int value)
Definition: am335xgpio.c:103
#define AM335XGPIO_SET_LOW(gpio_config)
Definition: am335xgpio.c:58
static bool is_gpio_config_valid(const struct adapter_gpio_config *gpio_config)
Definition: am335xgpio.c:87
#define AM335XGPIO_GPIO0_HW_ADDR
Definition: am335xgpio.c:25
static int am335xgpio_blink(int on)
Definition: am335xgpio.c:276
static const char *const am335xgpio_transports[]
Definition: am335xgpio.c:351
static int speed_offset
Definition: am335xgpio.c:82
static enum amx335gpio_initial_gpio_mode get_gpio_mode(const struct adapter_gpio_config *gpio_config)
Definition: am335xgpio.c:135
#define AM335XGPIO_GPIO_DATAIN_OFFSET
Definition: am335xgpio.c:35
static void am335xgpio_swdio_drive(bool is_output)
Definition: am335xgpio.c:258
static int get_gpio_value(const struct adapter_gpio_config *gpio_config)
Definition: am335xgpio.c:95
static enum amx335gpio_initial_gpio_mode initial_gpio_mode[ADAPTER_GPIO_IDX_NUM]
Definition: am335xgpio.c:78
static void initialize_gpio(enum adapter_gpio_config_index idx)
Definition: am335xgpio.c:159
#define AM335XGPIO_GPIO1_HW_ADDR
Definition: am335xgpio.c:26
static struct bitbang_interface am335xgpio_bitbang
Definition: am335xgpio.c:284
static bool am335xgpio_jtag_mode_possible(void)
Definition: am335xgpio.c:358
static bb_value_t am335xgpio_read(void)
Definition: am335xgpio.c:210
static int am335xgpio_reset(int trst, int srst)
Definition: am335xgpio.c:239
int bitbang_execute_queue(void)
Definition: bitbang.c:281
const struct swd_driver bitbang_swd
Definition: bitbang.c:569
bb_value_t
Definition: bitbang.h:16
@ BB_LOW
Definition: bitbang.h:17
@ BB_HIGH
Definition: bitbang.h:18
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:473
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
Definition: command.h:140
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:155
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:150
#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:425
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:247
@ COMMAND_CONFIG
Definition: command.h:41
@ COMMAND_ANY
Definition: command.h:42
#define DEBUG_CAP_TMS_SEQ
Definition: interface.h:189
bool transport_is_jtag(void)
Returns true if the current debug session is using JTAG as its transport.
Definition: jtag/core.c:1828
#define ERROR_JTAG_INIT_FAILED
Definition: jtag.h:549
#define LOG_WARNING(expr ...)
Definition: log.h:120
#define ERROR_FAIL
Definition: log.h:161
#define LOG_ERROR(expr ...)
Definition: log.h:123
#define LOG_INFO(expr ...)
Definition: log.h:117
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:155
#define BIT(nr)
Definition: stm32l4x.h:18
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
Configuration options for a single GPIO.
Definition: adapter.h:58
enum adapter_gpio_pull pull
Definition: adapter.h:64
enum adapter_gpio_init_state init_state
Definition: adapter.h:62
enum adapter_gpio_drive_mode drive
Definition: adapter.h:61
Low level callbacks (for bitbang).
Definition: bitbang.h:29
bb_value_t(* read)(void)
Sample TDO and return the value.
Definition: bitbang.h:31
const char * name
Definition: command.h:229
const char * usage
a string listing the options and arguments, required or optional
Definition: command.h:235
Represents a driver for a debugging interface.
Definition: interface.h:184
unsigned supported
Bit vector listing capabilities exposed by this driver.
Definition: interface.h:188
#define NULL
Definition: usb.h:16