a71033e40947fa981297e2dc924943e4208e2283
[bbg-swd.git] / 0001-jtag-drivers-bbg-swd-New-SWD-driver.patch
1 From ca085bb0dab3a732e71b4ca5e87757cd8351508f Mon Sep 17 00:00:00 2001
2 From: NIIBE Yutaka <gniibe@fsij.org>
3 Date: Wed, 14 Mar 2018 17:56:39 +0900
4 Subject: [PATCH] jtag: drivers: bbg-swd: New SWD driver
5
6 ---
7  configure.ac                 |  23 ++-
8  src/jtag/drivers/Makefile.am |   3 +
9  src/jtag/drivers/bbg-swd.c   | 399 +++++++++++++++++++++++++++++++++++++++++++
10  src/jtag/drivers/bbg-swd.h   |  44 +++++
11  src/jtag/interfaces.c        |   6 +
12  5 files changed, 474 insertions(+), 1 deletion(-)
13  create mode 100644 src/jtag/drivers/bbg-swd.c
14  create mode 100644 src/jtag/drivers/bbg-swd.h
15
16 diff --git a/configure.ac b/configure.ac
17 index 6949402a..282f6e60 100644
18 --- a/configure.ac
19 +++ b/configure.ac
20 @@ -137,6 +137,9 @@ m4_define([LIBFTDI_ADAPTERS],
21  m4_define([LIBJAYLINK_ADAPTERS],
22         [[[jlink], [SEGGER J-Link Programmer], [JLINK]]])
23  
24 +m4_define([BBG_ADAPTERS],
25 +       [[[bbg_swd], [PocketBeagle PRU Programmer], [BBG_SWD]]])
26 +
27  
28  AC_ARG_ENABLE([doxygen-html],
29    AS_HELP_STRING([--disable-doxygen-html],
30 @@ -355,6 +358,10 @@ AC_ARG_ENABLE([remote-bitbang],
31    AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang jtag driver]),
32    [build_remote_bitbang=$enableval], [build_remote_bitbang=no])
33  
34 +AC_ARG_ENABLE([bbg-swd],
35 +  AS_HELP_STRING([--enable-bbg-swd], [Enable building support for BBG-SWD.]),
36 +  [build_bbg_swd=$enableval], [build_bbg_swd=no])
37 +
38  AC_MSG_CHECKING([whether to enable dummy minidriver])
39  AS_IF([test "x$build_minidriver_dummy" = "xyes"], [
40    AS_IF([test "x$build_minidriver" = "xyes"], [
41 @@ -572,6 +579,19 @@ AS_IF([test "x$build_sysfsgpio" = "xyes"], [
42    AC_DEFINE([BUILD_SYSFSGPIO], [0], [0 if you don't want SysfsGPIO driver.])
43  ])
44  
45 +AS_IF([test "x$build_bbg_swd" = "xyes"], [
46 +  build_bbg_swd=yes
47 +  AC_SEARCH_LIBS([prussdrv_init], [prussdrv], [], [
48 +    AC_MSG_FAILURE([[
49 +*** Could not find the prussdrv library.
50 +*** Please install it from am335x_pru_package.
51 +]])
52 +  ])
53 +  AC_DEFINE([BUILD_BBG_SWD], [1], [1 if you want the BBG-SWD driver.])
54 +], [
55 +  AC_DEFINE([BUILD_BBG_SWD], [0], [0 if you don't want the BBG-SWD driver.])
56 +])
57 +
58  PKG_CHECK_MODULES([LIBUSB1], [libusb-1.0], [
59         use_libusb1=yes
60         AC_DEFINE([HAVE_LIBUSB1], [1], [Define if you have libusb-1.x])
61 @@ -679,6 +699,7 @@ AM_CONDITIONAL([OOCD_TRACE], [test "x$build_oocd_trace" = "xyes"])
62  AM_CONDITIONAL([REMOTE_BITBANG], [test "x$build_remote_bitbang" = "xyes"])
63  AM_CONDITIONAL([BUSPIRATE], [test "x$build_buspirate" = "xyes"])
64  AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"])
65 +AM_CONDITIONAL([BBG_SWD], [test "x$build_bbg_swd" = "xyes"])
66  AM_CONDITIONAL([USE_LIBUSB0], [test "x$use_libusb0" = "xyes"])
67  AM_CONDITIONAL([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"])
68  AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"])
69 @@ -756,7 +777,7 @@ echo
70  echo OpenOCD configuration summary
71  echo --------------------------------------------------
72  m4_foreach([adapter], [USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS,
73 -       HIDAPI_ADAPTERS, LIBFTDI_ADAPTERS, LIBJAYLINK_ADAPTERS],
74 +       HIDAPI_ADAPTERS, LIBFTDI_ADAPTERS, LIBJAYLINK_ADAPTERS, BBG_ADAPTERS],
75         [s=m4_format(["%-40s"], ADAPTER_DESC([adapter]))
76         AS_CASE([$ADAPTER_VAR([adapter])],
77                 [auto], [
78 diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
79 index e4114126..cd7de739 100644
80 --- a/src/jtag/drivers/Makefile.am
81 +++ b/src/jtag/drivers/Makefile.am
82 @@ -152,6 +152,9 @@ endif
83  if CMSIS_DAP
84  DRIVERFILES += %D%/cmsis_dap_usb.c
85  endif
86 +if BBG_SWD
87 +DRIVERFILES += %D%/bbg-swd.c
88 +endif
89  
90  DRIVERHEADERS = \
91         %D%/bitbang.h \
92 diff --git a/src/jtag/drivers/bbg-swd.c b/src/jtag/drivers/bbg-swd.c
93 new file mode 100644
94 index 00000000..2a4fa812
95 --- /dev/null
96 +++ b/src/jtag/drivers/bbg-swd.c
97 @@ -0,0 +1,399 @@
98 +/***************************************************************************
99 + *   Copyright (C) 2016  Flying Stone Technology                           *
100 + *   Author: NIIBE Yutaka <gniibe@fsij.org>                                *
101 + *                                                                         *
102 + *   This program is free software; you can redistribute it and/or modify  *
103 + *   it under the terms of the GNU General Public License as published by  *
104 + *   the Free Software Foundation; either version 2 of the License, or     *
105 + *   (at your option) any later version.                                   *
106 + *                                                                         *
107 + *   This program is distributed in the hope that it will be useful,       *
108 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
109 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
110 + *   GNU General Public License for more details.                          *
111 + *                                                                         *
112 + *   You should have received a copy of the GNU General Public License     *
113 + *   along with this program; if not, write to the                         *
114 + *   Free Software Foundation, Inc.,                                       *
115 + *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
116 + ***************************************************************************/
117 +
118 +#ifdef HAVE_CONFIG_H
119 +#include "config.h"
120 +#endif
121 +
122 +#include <jtag/interface.h>
123 +#include <jtag/commands.h>
124 +#include <jtag/swd.h>
125 +
126 +#include <prussdrv.h>
127 +#include <pruss_intc_mapping.h>
128 +
129 +#define PRU_NUM         0
130 +
131 +extern struct jtag_interface *jtag_interface;
132 +static void bbg_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk);
133 +static int bbg_swd_switch_seq(enum swd_special_seq seq);
134 +
135 +static void pru_request_cmd(uint32_t *p)
136 +{
137 +       /* Wakeup the PRU0 which sleeps.  */
138 +       prussdrv_pru_send_event(ARM_PRU0_INTERRUPT);
139 +
140 +       /* Wait PRU0 response.  */
141 +       prussdrv_pru_wait_event(PRU_EVTOUT_0);
142 +       prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
143 +       if ((p[0] & 0xff) == 4 || (p[0] & 0xff) == 5 || (p[0] & 0xff) == 7)
144 +               LOG_DEBUG("BBD-SWD: command execution (%08x:%08x)", p[0], p[1]);
145 +       else
146 +               LOG_DEBUG("BBD-SWD: command execution (%08x)", p[0]);
147 +}
148 +
149 +static int queued_retval;
150 +
151 +#define PRU_SWD_PROGRAM_PATH PKGDATADIR "/bbg-swd/pru-swd.bin"
152 +
153 +static uint32_t *pru_data_ram;
154 +static tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
155 +
156 +static int bbg_swd_open(void)
157 +{
158 +       int r;
159 +
160 +       LOG_DEBUG("bbg_swd_init");
161 +
162 +       /* Initialize the PRUSS driver.  */
163 +       prussdrv_init();
164 +
165 +       /* Open PRU interrupt to Host.  */
166 +       r = prussdrv_open(PRU_EVTOUT_0);
167 +       if (r < 0) {
168 +               LOG_ERROR("prussdrv_open open failed: %d", r);
169 +               return ERROR_FAIL;
170 +       }
171 +
172 +       /* Initialize PRU interrupt controller.  */
173 +       prussdrv_pruintc_init(&pruss_intc_initdata);
174 +
175 +       /* Initialize PRU memory access from Host.  */
176 +       r = prussdrv_map_prumem(PRUSS0_PRU0_DATARAM, (void **)&pru_data_ram);
177 +       if (r < 0) {
178 +               prussdrv_exit();
179 +               LOG_ERROR("prussdrv_map_prumem failed: %d", r);
180 +               return ERROR_FAIL;
181 +       }
182 +
183 +       /* Execute example on PRU */
184 +       LOG_DEBUG("Executing PRU-SWU program on PRUSS");
185 +       r = prussdrv_exec_program(PRU_NUM, PRU_SWD_PROGRAM_PATH);
186 +       if (r < 0) {
187 +               prussdrv_exit();
188 +               LOG_ERROR("prussdrv_exec_program failed: %d", r);
189 +               return ERROR_FAIL;
190 +       }
191 +       return ERROR_OK;
192 +}
193 +
194 +
195 +static int bbg_swd_close(void)
196 +{
197 +       /* Disable PRU.  */
198 +       prussdrv_pru_disable(PRU_NUM);
199 +       prussdrv_exit();
200 +       return ERROR_OK;
201 +}
202 +
203 +
204 +static void bbg_swd_gpio_srst(int on);
205 +
206 +static bool swd_mode;
207 +
208 +static int bbg_swd_interface_init(void)
209 +{
210 +       int retval;
211 +       enum reset_types jtag_reset_config = jtag_get_reset_config();
212 +
213 +       if (swd_mode) {
214 +               retval = bbg_swd_open();
215 +               if (retval != ERROR_OK)
216 +                       return retval;
217 +       }
218 +
219 +       if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
220 +               if (jtag_reset_config & RESET_SRST_NO_GATING) {
221 +                       bbg_swd_gpio_srst(0);
222 +                       LOG_INFO("Connecting under reset");
223 +               }
224 +       }
225 +
226 +       LOG_INFO("BBG-SWD: Interface ready");
227 +
228 +       return ERROR_OK;
229 +}
230 +
231 +static int bbg_swd_interface_quit(void)
232 +{
233 +       bbg_swd_close();
234 +       return ERROR_OK;
235 +}
236 +
237 +static int bbg_swd_swd_init(void)
238 +{
239 +       swd_mode = true;
240 +       return ERROR_OK;
241 +}
242 +
243 +enum {
244 +       CMD_HALT = 0,
245 +       CMD_BLINK,
246 +       CMD_GPIO_OUT,
247 +       CMD_GPIO_IN,
248 +       CMD_SIG_IDLE,
249 +       CMD_SIG_GEN,
250 +       CMD_READ_REG,
251 +       CMD_WRITE_REG
252 +};
253 +
254 +#define BBG_SWS_RESULT 16
255 +
256 +static void bbg_swd_idle(int count)
257 +{
258 +       pru_data_ram[0] = CMD_SIG_IDLE;
259 +       pru_data_ram[1] = count;
260 +       pru_request_cmd(pru_data_ram);
261 +}
262 +
263 +static void bbg_swd_gpio_srst(int signal)
264 +{
265 +       pru_data_ram[0] = CMD_GPIO_OUT;
266 +       pru_data_ram[1] = (1 << 15);
267 +       pru_data_ram[2] = signal ? 1 : 0;
268 +       pru_request_cmd(pru_data_ram);
269 +}
270 +
271 +static int bbg_swd_switch_seq(enum swd_special_seq seq)
272 +{
273 +       LOG_DEBUG("bbg_swd_switch_seq");
274 +
275 +       switch (seq) {
276 +       case LINE_RESET:
277 +               LOG_DEBUG("SWD line reset");
278 +               pru_data_ram[0] = CMD_SIG_GEN | (swd_seq_line_reset_len << 8);
279 +               memcpy (&pru_data_ram[1], swd_seq_line_reset, (swd_seq_line_reset_len+7)/8);
280 +               pru_request_cmd(pru_data_ram);
281 +               break;
282 +       case JTAG_TO_SWD:
283 +               LOG_DEBUG("JTAG-to-SWD");
284 +               pru_data_ram[0] = CMD_SIG_GEN | ((swd_seq_jtag_to_swd_len)<< 8);
285 +               memcpy (&pru_data_ram[1], swd_seq_jtag_to_swd, (swd_seq_jtag_to_swd_len+7)/8);
286 +               pru_request_cmd(pru_data_ram);
287 +               bbg_swd_idle(8);
288 +               break;
289 +       case SWD_TO_JTAG:
290 +               LOG_DEBUG("SWD-to-JTAG");
291 +               pru_data_ram[0] = CMD_SIG_GEN | (swd_seq_swd_to_jtag_len << 8);
292 +               memcpy (&pru_data_ram[1], swd_seq_swd_to_jtag, (swd_seq_swd_to_jtag_len+7)/8);
293 +               pru_request_cmd(pru_data_ram);
294 +               break;
295 +       default:
296 +               LOG_ERROR("Sequence %d not supported", seq);
297 +               return ERROR_FAIL;
298 +       }
299 +
300 +       return ERROR_OK;
301 +}
302 +
303 +
304 +static void bbg_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk)
305 +{
306 +       int ack;
307 +       int parity;
308 +       uint32_t data;
309 +       uint32_t delay = 0;
310 +
311 +       LOG_DEBUG("bbg_swd_read_reg");
312 +       assert(cmd & SWD_CMD_RnW);
313 +       assert(ap_delay_clk < 256);
314 +
315 +       if (queued_retval != ERROR_OK) {
316 +               LOG_DEBUG("Skip bbg_swd_read_reg because queued_retval=%d", queued_retval);
317 +               return;
318 +       }
319 +
320 +       if (cmd & SWD_CMD_APnDP)
321 +               delay = ap_delay_clk;
322 +
323 +       cmd |= 0x81;
324 +       pru_data_ram[0] = CMD_READ_REG | (cmd << 8) | (delay << 24);
325 +       pru_request_cmd(pru_data_ram);
326 +       ack = pru_data_ram[BBG_SWS_RESULT] & 0x07;
327 +       parity = (pru_data_ram[BBG_SWS_RESULT] & 0x80000000) != 0;
328 +       data = pru_data_ram[BBG_SWS_RESULT+1];
329 +
330 +       LOG_DEBUG("%s %s %s reg %X = %08" PRIx32,
331 +                 ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
332 +                 cmd & SWD_CMD_APnDP ? "AP" : "DP",
333 +                 cmd & SWD_CMD_RnW ? "read" : "write",
334 +                 (cmd & SWD_CMD_A32) >> 1,
335 +                 data);
336 +
337 +       if (ack != SWD_ACK_OK) {
338 +               queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
339 +       } else if (parity != parity_u32(data)) {
340 +               LOG_DEBUG("Wrong parity detected (%d)", parity);
341 +               queued_retval = ERROR_FAIL;
342 +       } else if (value) {
343 +               *value = data;
344 +               queued_retval = ERROR_OK;
345 +       }
346 +}
347 +
348 +static void bbg_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk)
349 +{
350 +       int ack;
351 +       int parity = parity_u32(value);
352 +       uint32_t delay = 0;
353 +
354 +       LOG_DEBUG("bbg_swd_write_reg");
355 +       assert(!(cmd & SWD_CMD_RnW));
356 +       assert(ap_delay_clk < 256);
357 +
358 +       if (queued_retval != ERROR_OK) {
359 +               LOG_DEBUG("Skip bbg_swd_write_reg because queued_retval=%d", queued_retval);
360 +               return;
361 +       }
362 +
363 +       if (cmd & SWD_CMD_APnDP)
364 +               delay = ap_delay_clk;
365 +
366 +       cmd |= 0x81;
367 +       pru_data_ram[0] = CMD_WRITE_REG | (cmd << 8) | (parity << 16) | (delay << 24);
368 +       pru_data_ram[1] = value;
369 +       pru_request_cmd(pru_data_ram);
370 +       ack = pru_data_ram[BBG_SWS_RESULT] & 0x07;
371 +
372 +       LOG_DEBUG("%s %s %s reg %X = %08" PRIx32,
373 +                 ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
374 +                 cmd & SWD_CMD_APnDP ? "AP" : "DP",
375 +                 cmd & SWD_CMD_RnW ? "read" : "write",
376 +                 (cmd & SWD_CMD_A32) >> 1,
377 +                 value);
378 +
379 +       if (ack != SWD_ACK_OK)
380 +               queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
381 +}
382 +
383 +static int bbg_swd_run_queue(void)
384 +{
385 +       int retval;
386 +
387 +       LOG_DEBUG("bbg_swd_run_queue");
388 +       bbg_swd_idle(8);
389 +       retval = queued_retval;
390 +       queued_retval = ERROR_OK;
391 +       LOG_DEBUG("SWD queue return value: %02x", retval);
392 +       return retval;
393 +}
394 +
395 +const struct swd_driver bbg_swd = {
396 +       .init = bbg_swd_swd_init,
397 +       .switch_seq = bbg_swd_switch_seq,
398 +       .read_reg = bbg_swd_read_reg,
399 +       .write_reg = bbg_swd_write_reg,
400 +       .run = bbg_swd_run_queue,
401 +};
402 +
403 +
404 +static const char * const bbg_swd_transport[] = { "swd", NULL };
405 +
406 +
407 +COMMAND_HANDLER(bbg_swd_handle_hello_command)
408 +{
409 +       puts("Hello!");
410 +       return ERROR_OK;
411 +}
412 +
413 +static const struct command_registration bbg_swd_command_handlers[] = {
414 +       {
415 +               .name = "bbg_swd_hello",
416 +               .handler = &bbg_swd_handle_hello_command,
417 +               .mode = COMMAND_CONFIG,
418 +               .help = "hello command for BBG-SWD",
419 +               .usage = "<cmd>",
420 +       },
421 +       COMMAND_REGISTRATION_DONE
422 +};
423 +
424 +static void bbg_swd_execute_reset(struct jtag_command *cmd)
425 +{
426 +       bbg_swd_gpio_srst(cmd->cmd.reset->srst ? 0: 1);
427 +}
428 +
429 +static void bbg_swd_execute_sleep(struct jtag_command *cmd)
430 +{
431 +       jtag_sleep(cmd->cmd.sleep->us);
432 +}
433 +
434 +static void bbg_swd_execute_command(struct jtag_command *cmd)
435 +{
436 +       switch (cmd->type) {
437 +               case JTAG_RESET:
438 +                       bbg_swd_execute_reset(cmd);
439 +                       break;
440 +               case JTAG_SLEEP:
441 +                       bbg_swd_execute_sleep(cmd);
442 +                       break;
443 +               default:
444 +                       LOG_ERROR("BUG: unknown JTAG command type encountered");
445 +                       exit(-1);
446 +       }
447 +}
448 +
449 +static int bbg_swd_interface_execute_queue(void)
450 +{
451 +       struct jtag_command *cmd = jtag_command_queue;
452 +
453 +       while (cmd != NULL) {
454 +               bbg_swd_execute_command(cmd);
455 +               cmd = cmd->next;
456 +       }
457 +
458 +       return ERROR_OK;
459 +}
460 +
461 +static int bbg_swd_interface_speed(int speed)
462 +{
463 +       return ERROR_OK;
464 +}
465 +
466 +static int bbg_swd_interface_speed_div(int speed, int *khz)
467 +{
468 +       *khz = speed;
469 +       return ERROR_OK;
470 +}
471 +
472 +static int bbg_swd_interface_khz(int khz, int *jtag_speed)
473 +{
474 +       *jtag_speed = khz;
475 +       return ERROR_OK;
476 +}
477 +
478 +struct jtag_interface bbg_swd_interface = {
479 +       .name = "bbg-swd",
480 +       .commands = bbg_swd_command_handlers,
481 +       .swd = &bbg_swd,
482 +       .transports = bbg_swd_transport,
483 +
484 +       .execute_queue = bbg_swd_interface_execute_queue,
485 +       .speed = bbg_swd_interface_speed,
486 +       .speed_div = bbg_swd_interface_speed_div,
487 +       .khz = bbg_swd_interface_khz,
488 +
489 +       .init = bbg_swd_interface_init,
490 +       .quit = bbg_swd_interface_quit,
491 +};
492 +/*
493 + * Local Variables:
494 + * c-file-style: "linux"
495 + * End:
496 + */
497 diff --git a/src/jtag/drivers/bbg-swd.h b/src/jtag/drivers/bbg-swd.h
498 new file mode 100644
499 index 00000000..f0c92b3f
500 --- /dev/null
501 +++ b/src/jtag/drivers/bbg-swd.h
502 @@ -0,0 +1,44 @@
503 +/***************************************************************************
504 + *   Copyright (C) 2016  Flying Stone Technology                           *
505 + *   Author: NIIBE Yutaka <gniibe@fsij.org>                                *
506 + *                                                                         *
507 + *   This program is free software; you can redistribute it and/or modify  *
508 + *   it under the terms of the GNU General Public License as published by  *
509 + *   the Free Software Foundation; either version 2 of the License, or     *
510 + *   (at your option) any later version.                                   *
511 + *                                                                         *
512 + *   This program is distributed in the hope that it will be useful,       *
513 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
514 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
515 + *   GNU General Public License for more details.                          *
516 + *                                                                         *
517 + *   You should have received a copy of the GNU General Public License     *
518 + *   along with this program; if not, write to the                         *
519 + *   Free Software Foundation, Inc.,                                       *
520 + *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
521 + ***************************************************************************/
522 +
523 +#ifndef BBG_SWD_H
524 +#define BBG_SWD_H
525 +
526 +#include <jtag/swd.h>
527 +
528 +struct bbg_swd_interface {
529 +       /* low level callbacks (for bbg_swd)
530 +        */
531 +       int (*read)(void);
532 +       void (*write)(int tck, int tms, int tdi);
533 +       void (*reset)(int trst, int srst);
534 +       void (*blink)(int on);
535 +       int (*swdio_read)(void);
536 +       void (*swdio_drive)(bool on);
537 +};
538 +
539 +const struct swd_driver bbg_swd_swd;
540 +
541 +int bbg_swd_execute_queue(void);
542 +
543 +extern struct jtag_interface bbg_swd_interface;
544 +int bbg_swd_swd_switch_seq(enum swd_special_seq seq);
545 +
546 +#endif /* BBG_SWD_H */
547 diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c
548 index ad656a84..cbd08c79 100644
549 --- a/src/jtag/interfaces.c
550 +++ b/src/jtag/interfaces.c
551 @@ -123,6 +123,9 @@ extern struct jtag_interface bcm2835gpio_interface;
552  #if BUILD_CMSIS_DAP == 1
553  extern struct jtag_interface cmsis_dap_interface;
554  #endif
555 +#if BUILD_BBG_SWD == 1
556 +extern struct jtag_interface bbg_swd_interface;
557 +#endif
558  #endif /* standard drivers */
559  
560  /**
561 @@ -216,6 +219,9 @@ struct jtag_interface *jtag_interfaces[] = {
562  #if BUILD_CMSIS_DAP == 1
563                 &cmsis_dap_interface,
564  #endif
565 +#if BUILD_BBG_SWD == 1
566 +               &bbg_swd_interface,
567 +#endif
568  #endif /* standard drivers */
569                 NULL,
570         };
571 -- 
572 2.11.0
573