OpenOCD
adi_v5_swd.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  *
5  * Copyright (C) 2010 by David Brownell
6  ***************************************************************************/
7 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #include "arm.h"
38 #include "arm_adi_v5.h"
39 #include <helper/time_support.h>
40 
41 #include <transport/transport.h>
42 #include <jtag/interface.h>
43 
44 #include <jtag/swd.h>
45 
46 /* for debug, set do_sync to true to force synchronous transfers */
47 static bool do_sync;
48 
50 
52 
53 
54 static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg,
55  uint32_t data);
56 
57 
58 static int swd_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq)
59 {
60  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
61  assert(swd);
62 
63  return swd->switch_seq(seq);
64 }
65 
66 static void swd_finish_read(struct adiv5_dap *dap)
67 {
68  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
69  if (dap->last_read) {
70  swd->read_reg(swd_cmd(true, false, DP_RDBUFF), dap->last_read, 0);
71  dap->last_read = NULL;
72  }
73 }
74 
75 static void swd_clear_sticky_errors(struct adiv5_dap *dap)
76 {
77  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
78  assert(swd);
79 
80  swd->write_reg(swd_cmd(false, false, DP_ABORT),
82 }
83 
84 static int swd_run_inner(struct adiv5_dap *dap)
85 {
86  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
87 
88  return swd->run();
89 }
90 
91 static inline int check_sync(struct adiv5_dap *dap)
92 {
93  return do_sync ? swd_run_inner(dap) : ERROR_OK;
94 }
95 
97 static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned int reg)
98 {
99  /* Only register address 0 (ADIv6 only) and 4 are banked. */
100  if (is_adiv6(dap) ? (reg & 0xf) > 4 : (reg & 0xf) != 4)
101  return ERROR_OK;
102 
103  uint32_t sel = (reg >> 4) & DP_SELECT_DPBANK;
104 
105  /* ADIv6 ensures DPBANKSEL = 0 after line reset */
106  if ((dap->select_valid || (is_adiv6(dap) && dap->select_dpbanksel_valid))
107  && (sel == (dap->select & DP_SELECT_DPBANK)))
108  return ERROR_OK;
109 
110  /* Use the AP part of dap->select regardless of dap->select_valid:
111  * if !dap->select_valid
112  * dap->select contains a speculative value likely going to be used
113  * in the following swd_queue_ap_bankselect() */
114  sel |= (uint32_t)(dap->select & SELECT_AP_MASK);
115 
116  LOG_DEBUG_IO("DP BANK SELECT: %" PRIx32, sel);
117 
118  /* dap->select cache gets updated in the following call */
119  return swd_queue_dp_write_inner(dap, DP_SELECT, sel);
120 }
121 
122 static int swd_queue_dp_read_inner(struct adiv5_dap *dap, unsigned int reg,
123  uint32_t *data)
124 {
125  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
126  assert(swd);
127 
128  int retval = swd_queue_dp_bankselect(dap, reg);
129  if (retval != ERROR_OK)
130  return retval;
131 
132  swd->read_reg(swd_cmd(true, false, reg), data, 0);
133 
134  return check_sync(dap);
135 }
136 
137 static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg,
138  uint32_t data)
139 {
140  int retval = ERROR_OK;
141  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
142  assert(swd);
143 
144  swd_finish_read(dap);
145 
146  if (reg == DP_SELECT) {
147  dap->select = data | (dap->select & (0xffffffffull << 32));
148 
149  swd->write_reg(swd_cmd(false, false, reg), data, 0);
150 
151  retval = check_sync(dap);
152  dap->select_valid = (retval == ERROR_OK);
154 
155  return retval;
156  }
157 
158  if (reg == DP_SELECT1)
159  dap->select = ((uint64_t)data << 32) | (dap->select & 0xffffffffull);
160 
161  /* DP_ABORT write is not banked.
162  * Prevent writing DP_SELECT before as it would fail on locked up DP */
163  if (reg != DP_ABORT)
164  retval = swd_queue_dp_bankselect(dap, reg);
165 
166  if (retval == ERROR_OK) {
167  swd->write_reg(swd_cmd(false, false, reg), data, 0);
168 
169  retval = check_sync(dap);
170  }
171 
172  if (reg == DP_SELECT1)
173  dap->select1_valid = (retval == ERROR_OK);
174 
175  return retval;
176 }
177 
178 
179 static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr,
180  uint32_t *dlpidr_ptr, bool clear_sticky)
181 {
182  int retval;
183  uint32_t dpidr, dlpidr;
184 
185  assert(dap_is_multidrop(dap));
186 
187  /* Send JTAG_TO_DORMANT and DORMANT_TO_SWD just once
188  * and then use shorter LINE_RESET until communication fails */
192  } else {
194  }
195 
196  /*
197  * Zero dap->select and set dap->select_dpbanksel_valid
198  * to skip the write to DP_SELECT before DPIDR read, avoiding
199  * the protocol error.
200  * Clear the other validity flags because the rest of the DP
201  * SELECT and SELECT1 registers is unknown after line reset.
202  */
203  dap->select = 0;
204  dap->select_dpbanksel_valid = true;
205  dap->select_valid = false;
206  dap->select1_valid = false;
207 
209  if (retval != ERROR_OK)
210  return retval;
211 
212  retval = swd_queue_dp_read_inner(dap, DP_DPIDR, &dpidr);
213  if (retval != ERROR_OK)
214  return retval;
215 
216  if (clear_sticky) {
217  /* Clear all sticky errors (including ORUN) */
219  } else {
220  /* Ideally just clear ORUN flag which is set by reset */
222  if (retval != ERROR_OK)
223  return retval;
224  }
225 
226  retval = swd_queue_dp_read_inner(dap, DP_DLPIDR, &dlpidr);
227  if (retval != ERROR_OK)
228  return retval;
229 
230  retval = swd_run_inner(dap);
231  if (retval != ERROR_OK)
232  return retval;
233 
234  if ((dpidr & DP_DPIDR_VERSION_MASK) < (2UL << DP_DPIDR_VERSION_SHIFT)) {
235  LOG_INFO("Read DPIDR 0x%08" PRIx32
236  " has version < 2. A non multidrop capable device connected?",
237  dpidr);
238  return ERROR_FAIL;
239  }
240 
241  /* TODO: check TARGETID if DLIPDR is same for more than one DP */
242  uint32_t expected_dlpidr = DP_DLPIDR_PROTVSN |
244  if (dlpidr != expected_dlpidr) {
245  LOG_INFO("Read incorrect DLPIDR 0x%08" PRIx32
246  " (possibly CTRL/STAT value)",
247  dlpidr);
248  return ERROR_FAIL;
249  }
250 
251  LOG_DEBUG_IO("Selected DP_TARGETSEL 0x%08" PRIx32, dap->multidrop_targetsel);
254 
255  if (dpidr_ptr)
256  *dpidr_ptr = dpidr;
257 
258  if (dlpidr_ptr)
259  *dlpidr_ptr = dlpidr;
260 
261  return retval;
262 }
263 
264 static int swd_multidrop_select(struct adiv5_dap *dap)
265 {
266  if (!dap_is_multidrop(dap))
267  return ERROR_OK;
268 
269  if (swd_multidrop_selected_dap == dap)
270  return ERROR_OK;
271 
272  int retval = ERROR_OK;
273  for (unsigned int retry = 0; ; retry++) {
274  bool clear_sticky = retry > 0;
275 
276  retval = swd_multidrop_select_inner(dap, NULL, NULL, clear_sticky);
277  if (retval == ERROR_OK)
278  break;
279 
281  if (retry > 3) {
282  LOG_ERROR("Failed to select multidrop %s", adiv5_dap_name(dap));
283  dap->do_reconnect = true;
284  return retval;
285  }
286 
287  LOG_DEBUG("Failed to select multidrop %s, retrying...",
288  adiv5_dap_name(dap));
289  }
290 
291  dap->do_reconnect = false;
292  return retval;
293 }
294 
295 static int swd_connect_multidrop(struct adiv5_dap *dap)
296 {
297  int retval;
298  uint32_t dpidr = 0xdeadbeef;
299  uint32_t dlpidr = 0xdeadbeef;
300  int64_t timeout = timeval_ms() + 500;
301 
302  do {
303  /* Do not make any assumptions about SWD state in case of reconnect */
304  if (dap->do_reconnect)
306 
307  /* Clear link state, including the SELECT cache. */
308  dap->do_reconnect = false;
311 
312  retval = swd_multidrop_select_inner(dap, &dpidr, &dlpidr, true);
313  if (retval == ERROR_OK)
314  break;
315 
317  alive_sleep(1);
318 
319  } while (timeval_ms() < timeout);
320 
321  if (retval != ERROR_OK) {
323  LOG_ERROR("Failed to connect multidrop %s", adiv5_dap_name(dap));
324  return retval;
325  }
326 
328  LOG_INFO("SWD DPIDR 0x%08" PRIx32 ", DLPIDR 0x%08" PRIx32,
329  dpidr, dlpidr);
330 
331  return retval;
332 }
333 
334 static int swd_connect_single(struct adiv5_dap *dap)
335 {
336  int retval;
337  uint32_t dpidr = 0xdeadbeef;
338  int64_t timeout = timeval_ms() + 500;
339 
340  do {
341  if (dap->switch_through_dormant) {
344  } else {
346  }
347 
348  /* Clear link state, including the SELECT cache. */
349  dap->do_reconnect = false;
351 
352  /* The sequences to enter in SWD (JTAG_TO_SWD and DORMANT_TO_SWD) end
353  * with a SWD line reset sequence (50 clk with SWDIO high).
354  * From ARM IHI 0031F ADIv5.2 and ARM IHI 0074C ADIv6.0,
355  * chapter B4.3.3 "Connection and line reset sequence":
356  * - DPv3 (ADIv6) only: line reset sets DP_SELECT_DPBANK to zero;
357  * - read of DP_DPIDR takes the connection out of reset;
358  * - write of DP_TARGETSEL keeps the connection in reset;
359  * - other accesses return protocol error (SWDIO not driven by target).
360  *
361  * dap_invalidate_cache() sets dap->select to zero and all validity
362  * flags to invalid. Set dap->select_dpbanksel_valid only
363  * to skip the write to DP_SELECT, avoiding the protocol error.
364  * Read DP_DPIDR to get out of reset.
365  */
366  dap->select_dpbanksel_valid = true;
367 
368  retval = swd_queue_dp_read_inner(dap, DP_DPIDR, &dpidr);
369  if (retval == ERROR_OK) {
370  retval = swd_run_inner(dap);
371  if (retval == ERROR_OK)
372  break;
373  }
374 
375  alive_sleep(1);
376 
378  } while (timeval_ms() < timeout);
379 
380  if (retval != ERROR_OK) {
381  LOG_ERROR("Error connecting DP: cannot read IDR");
382  return retval;
383  }
384 
385  LOG_INFO("SWD DPIDR 0x%08" PRIx32, dpidr);
386 
387  do {
388  dap->do_reconnect = false;
389 
390  /* force clear all sticky faults */
392 
393  retval = swd_run_inner(dap);
394  if (retval != ERROR_WAIT)
395  break;
396 
397  alive_sleep(10);
398 
399  } while (timeval_ms() < timeout);
400 
401  return retval;
402 }
403 
404 static int swd_pre_connect(struct adiv5_dap *dap)
405 {
407 
408  return ERROR_OK;
409 }
410 
411 static int swd_connect(struct adiv5_dap *dap)
412 {
413  int status;
414 
415  /* FIXME validate transport config ... is the
416  * configured DAP present (check IDCODE)?
417  */
418 
419  /* Check if we should reset srst already when connecting, but not if reconnecting. */
420  if (!dap->do_reconnect) {
422 
426  else
427  LOG_WARNING("\'srst_nogate\' reset_config option is required");
428  }
429  }
430 
431  if (dap_is_multidrop(dap))
433  else
434  status = swd_connect_single(dap);
435 
436  /* IHI 0031E B4.3.2:
437  * "A WAIT response must not be issued to the ...
438  * ... writes to the ABORT register"
439  * swd_clear_sticky_errors() writes to the ABORT register only.
440  *
441  * Unfortunately at least Microchip SAMD51/E53/E54 returns WAIT
442  * in a corner case. Just try if ABORT resolves the problem.
443  */
444  if (status == ERROR_WAIT) {
445  LOG_WARNING("Connecting DP: stalled AP operation, issuing ABORT");
446 
447  dap->do_reconnect = false;
448 
451 
452  if (status == ERROR_OK)
453  status = swd_run_inner(dap);
454  }
455 
456  if (status == ERROR_OK)
457  status = dap_dp_init(dap);
458 
459  return status;
460 }
461 
462 static int swd_check_reconnect(struct adiv5_dap *dap)
463 {
464  if (dap->do_reconnect)
465  return swd_connect(dap);
466 
467  return ERROR_OK;
468 }
469 
470 static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
471 {
472  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
473  assert(swd);
474 
475  /* TODO: Send DAPABORT in swd_multidrop_select_inner()
476  * in the case the multidrop dap is not selected?
477  * swd_queue_ap_abort() is not currently used anyway...
478  */
479  int retval = swd_multidrop_select(dap);
480  if (retval != ERROR_OK)
481  return retval;
482 
483  swd->write_reg(swd_cmd(false, false, DP_ABORT),
485  return check_sync(dap);
486 }
487 
488 static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned int reg,
489  uint32_t *data)
490 {
491  int retval = swd_check_reconnect(dap);
492  if (retval != ERROR_OK)
493  return retval;
494 
495  retval = swd_multidrop_select(dap);
496  if (retval != ERROR_OK)
497  return retval;
498 
499  return swd_queue_dp_read_inner(dap, reg, data);
500 }
501 
502 static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned int reg,
503  uint32_t data)
504 {
505  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
506  assert(swd);
507 
508  int retval = swd_check_reconnect(dap);
509  if (retval != ERROR_OK)
510  return retval;
511 
512  retval = swd_multidrop_select(dap);
513  if (retval != ERROR_OK)
514  return retval;
515 
516  return swd_queue_dp_write_inner(dap, reg, data);
517 }
518 
520 static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned int reg)
521 {
522  int retval;
523  struct adiv5_dap *dap = ap->dap;
524  uint64_t sel;
525 
526  if (is_adiv6(dap))
527  sel = ap->ap_num | (reg & 0x00000FF0);
528  else
529  sel = (ap->ap_num << 24) | (reg & ADIV5_DP_SELECT_APBANK);
530 
531  uint64_t sel_diff = (sel ^ dap->select) & SELECT_AP_MASK;
532 
533  bool set_select = !dap->select_valid || (sel_diff & 0xffffffffull);
534  bool set_select1 = is_adiv6(dap) && dap->asize > 32
535  && (!dap->select1_valid
536  || sel_diff & (0xffffffffull << 32));
537 
538  if (set_select && set_select1) {
539  /* Prepare DP bank for DP_SELECT1 now to save one write */
540  sel |= (DP_SELECT1 & 0x000000f0) >> 4;
541  } else {
542  /* Use the DP part of dap->select regardless of dap->select_valid:
543  * if !dap->select_valid
544  * dap->select contains a speculative value likely going to be used
545  * in the following swd_queue_dp_bankselect().
546  * Moreover dap->select_valid should never be false here as a DP bank
547  * is always selected before selecting an AP bank */
548  sel |= dap->select & DP_SELECT_DPBANK;
549  }
550 
551  if (set_select) {
552  LOG_DEBUG_IO("AP BANK SELECT: %" PRIx32, (uint32_t)sel);
553 
554  retval = swd_queue_dp_write(dap, DP_SELECT, (uint32_t)sel);
555  if (retval != ERROR_OK)
556  return retval;
557  }
558 
559  if (set_select1) {
560  LOG_DEBUG_IO("AP BANK SELECT1: %" PRIx32, (uint32_t)(sel >> 32));
561 
562  retval = swd_queue_dp_write(dap, DP_SELECT1, (uint32_t)(sel >> 32));
563  if (retval != ERROR_OK)
564  return retval;
565  }
566 
567  return ERROR_OK;
568 }
569 
570 static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned int reg,
571  uint32_t *data)
572 {
573  struct adiv5_dap *dap = ap->dap;
574  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
575  assert(swd);
576 
577  int retval = swd_check_reconnect(dap);
578  if (retval != ERROR_OK)
579  return retval;
580 
581  retval = swd_multidrop_select(dap);
582  if (retval != ERROR_OK)
583  return retval;
584 
585  retval = swd_queue_ap_bankselect(ap, reg);
586  if (retval != ERROR_OK)
587  return retval;
588 
589  swd->read_reg(swd_cmd(true, true, reg), dap->last_read, ap->memaccess_tck);
590  dap->last_read = data;
591 
592  return check_sync(dap);
593 }
594 
595 static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned int reg,
596  uint32_t data)
597 {
598  struct adiv5_dap *dap = ap->dap;
599  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
600  assert(swd);
601 
602  int retval = swd_check_reconnect(dap);
603  if (retval != ERROR_OK)
604  return retval;
605 
606  retval = swd_multidrop_select(dap);
607  if (retval != ERROR_OK)
608  return retval;
609 
610  swd_finish_read(dap);
611 
612  retval = swd_queue_ap_bankselect(ap, reg);
613  if (retval != ERROR_OK)
614  return retval;
615 
616  swd->write_reg(swd_cmd(false, true, reg), data, ap->memaccess_tck);
617 
618  return check_sync(dap);
619 }
620 
622 static int swd_run(struct adiv5_dap *dap)
623 {
624  int retval = swd_multidrop_select(dap);
625  if (retval != ERROR_OK)
626  return retval;
627 
628  swd_finish_read(dap);
629 
630  retval = swd_run_inner(dap);
631  if (retval != ERROR_OK) {
632  /* fault response */
633  dap->do_reconnect = true;
634  }
635 
636  return retval;
637 }
638 
640 static void swd_quit(struct adiv5_dap *dap)
641 {
642  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
643  static bool done;
644 
645  /* There is no difference if the sequence is sent at the last
646  * or the first swd_quit() call, send it just once */
647  if (done)
648  return;
649 
650  done = true;
651  if (dap_is_multidrop(dap)) {
652  /* Emit the switch seq to dormant state regardless the state mirrored
653  * in swd_multidrop_in_swd_state. Doing so ensures robust operation
654  * in the case the variable is out of sync.
655  * Sending SWD_TO_DORMANT makes no change if the DP is already dormant. */
658  /* Revisit!
659  * Leaving DPs in dormant state was tested and offers some safety
660  * against DPs mismatch in case of unintentional use of non-multidrop SWD.
661  * To put SWJ-DPs to power-on state issue
662  * swd->switch_seq(DORMANT_TO_JTAG);
663  */
664  } else {
665  if (dap->switch_through_dormant) {
668  } else {
669  swd->switch_seq(SWD_TO_JTAG);
670  }
671  }
672 
673  /* flush the queue to shift out the sequence before exit */
674  swd->run();
675 }
676 
677 const struct dap_ops swd_dap_ops = {
679  .connect = swd_connect,
680  .send_sequence = swd_send_sequence,
681  .queue_dp_read = swd_queue_dp_read,
682  .queue_dp_write = swd_queue_dp_write,
683  .queue_ap_read = swd_queue_ap_read,
684  .queue_ap_write = swd_queue_ap_write,
685  .queue_ap_abort = swd_queue_ap_abort,
686  .run = swd_run,
687  .quit = swd_quit,
688 };
689 
690 static const struct command_registration swd_commands[] = {
691  {
692  /*
693  * Set up SWD and JTAG targets identically, unless/until
694  * infrastructure improves ... meanwhile, ignore all
695  * JTAG-specific stuff like IR length for SWD.
696  *
697  * REVISIT can we verify "just one SWD DAP" here/early?
698  */
699  .name = "newdap",
700  .handler = handle_jtag_newtap,
701  .mode = COMMAND_CONFIG,
702  .help = "declare a new SWD DAP",
703  .usage = "basename dap_type ['-irlen' count] "
704  "['-enable'|'-disable'] "
705  "['-expected_id' number] "
706  "['-ignore-version'] "
707  "['-ignore-bypass'] "
708  "['-ircapture' number] "
709  "['-ir-bypass' number] "
710  "['-mask' number]",
711  },
713 };
714 
715 static const struct command_registration swd_handlers[] = {
716  {
717  .name = "swd",
718  .mode = COMMAND_ANY,
719  .help = "SWD command group",
720  .chain = swd_commands,
721  .usage = "",
722  },
724 };
725 
726 static int swd_select(struct command_context *ctx)
727 {
728  /* FIXME: only place where global 'adapter_driver' is still needed */
729  extern struct adapter_driver *adapter_driver;
730  const struct swd_driver *swd = adapter_driver->swd_ops;
731  int retval;
732 
733  retval = register_commands(ctx, NULL, swd_handlers);
734  if (retval != ERROR_OK)
735  return retval;
736 
737  /* be sure driver is in SWD mode; start
738  * with hardware default TRN (1), it can be changed later
739  */
740  if (!swd || !swd->read_reg || !swd->write_reg || !swd->init) {
741  LOG_DEBUG("no SWD driver?");
742  return ERROR_FAIL;
743  }
744 
745  retval = swd->init();
746  if (retval != ERROR_OK) {
747  LOG_DEBUG("can't init SWD driver");
748  return retval;
749  }
750 
751  return retval;
752 }
753 
754 static int swd_init(struct command_context *ctx)
755 {
756  /* nothing done here, SWD is initialized
757  * together with the DAP */
758  return ERROR_OK;
759 }
760 
761 static struct transport swd_transport = {
762  .name = "swd",
763  .select = swd_select,
764  .init = swd_init,
765 };
766 
767 static void swd_constructor(void) __attribute__((constructor));
768 static void swd_constructor(void)
769 {
771 }
772 
777 {
779 }
struct adapter_driver * adapter_driver
Definition: adapter.c:26
static int swd_multidrop_select(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:264
const struct dap_ops swd_dap_ops
Definition: adi_v5_swd.c:677
static int swd_connect_single(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:334
static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
Definition: adi_v5_swd.c:470
static const struct command_registration swd_commands[]
Definition: adi_v5_swd.c:690
static void swd_clear_sticky_errors(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:75
static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg, uint32_t data)
Definition: adi_v5_swd.c:137
static int check_sync(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:91
static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data)
Definition: adi_v5_swd.c:570
static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data)
Definition: adi_v5_swd.c:502
static int swd_run_inner(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:84
static int swd_connect(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:411
static int swd_pre_connect(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:404
static int swd_connect_multidrop(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:295
static int swd_init(struct command_context *ctx)
Definition: adi_v5_swd.c:754
static int swd_run(struct adiv5_dap *dap)
Executes all queued DAP operations.
Definition: adi_v5_swd.c:622
static int swd_select(struct command_context *ctx)
Definition: adi_v5_swd.c:726
static void swd_finish_read(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:66
static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned int reg)
Select the AP register bank.
Definition: adi_v5_swd.c:520
static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned int reg)
Select the DP register bank.
Definition: adi_v5_swd.c:97
static int swd_queue_dp_read_inner(struct adiv5_dap *dap, unsigned int reg, uint32_t *data)
Definition: adi_v5_swd.c:122
static struct transport swd_transport
Definition: adi_v5_swd.c:761
static bool swd_multidrop_in_swd_state
Definition: adi_v5_swd.c:51
bool transport_is_swd(void)
Returns true if the current debug session is using SWD as its transport.
Definition: adi_v5_swd.c:776
static bool do_sync
Definition: adi_v5_swd.c:47
static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data)
Definition: adi_v5_swd.c:595
static int swd_check_reconnect(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:462
static int swd_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq)
Definition: adi_v5_swd.c:58
static void swd_quit(struct adiv5_dap *dap)
Put the SWJ-DP back to JTAG mode.
Definition: adi_v5_swd.c:640
static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data)
Definition: adi_v5_swd.c:488
static const struct command_registration swd_handlers[]
Definition: adi_v5_swd.c:715
static struct adiv5_dap * swd_multidrop_selected_dap
Definition: adi_v5_swd.c:49
static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr, uint32_t *dlpidr_ptr, bool clear_sticky)
Definition: adi_v5_swd.c:179
static void swd_constructor(void)
Definition: adi_v5_swd.c:767
Holds the interface to ARM cores.
int dap_dp_init(struct adiv5_dap *dap)
Initialize a DAP.
Definition: arm_adi_v5.c:779
void dap_invalidate_cache(struct adiv5_dap *dap)
Invalidate cached DP select and cached TAR and CSW of all APs.
Definition: arm_adi_v5.c:756
This defines formats and data structures used to talk to ADIv5 entities.
#define DP_ABORT
Definition: arm_adi_v5.h:46
#define WDERRCLR
Definition: arm_adi_v5.h:71
#define DP_SELECT
Definition: arm_adi_v5.h:57
const struct swd_driver * adiv5_dap_swd_driver(struct adiv5_dap *self)
Definition: arm_dap.c:60
#define DP_TARGETSEL_INSTANCEID_MASK
Definition: arm_adi_v5.h:114
#define DP_SELECT1
Definition: arm_adi_v5.h:55
#define SELECT_AP_MASK
Definition: arm_adi_v5.h:107
#define STKERRCLR
Definition: arm_adi_v5.h:70
#define DP_DPIDR
Definition: arm_adi_v5.h:45
#define DP_RDBUFF
Definition: arm_adi_v5.h:58
#define DP_DLPIDR
Definition: arm_adi_v5.h:53
#define ORUNERRCLR
Definition: arm_adi_v5.h:72
#define DP_DLPIDR_PROTVSN
Definition: arm_adi_v5.h:98
#define STKCMPCLR
Definition: arm_adi_v5.h:69
#define DAPABORT
Definition: arm_adi_v5.h:68
#define DP_DPIDR_VERSION_MASK
Definition: arm_adi_v5.h:65
swd_special_seq
Definition: arm_adi_v5.h:236
@ DORMANT_TO_JTAG
Definition: arm_adi_v5.h:243
@ JTAG_TO_SWD
Definition: arm_adi_v5.h:238
@ DORMANT_TO_SWD
Definition: arm_adi_v5.h:242
@ LINE_RESET
Definition: arm_adi_v5.h:237
@ JTAG_TO_DORMANT
Definition: arm_adi_v5.h:239
@ SWD_TO_DORMANT
Definition: arm_adi_v5.h:241
@ SWD_TO_JTAG
Definition: arm_adi_v5.h:240
const char * adiv5_dap_name(struct adiv5_dap *self)
Definition: arm_dap.c:54
static bool is_adiv6(const struct adiv5_dap *dap)
Check if DAP is ADIv6.
Definition: arm_adi_v5.h:523
#define DP_TARGETSEL
Definition: arm_adi_v5.h:59
#define DP_DPIDR_VERSION_SHIFT
Definition: arm_adi_v5.h:64
static bool dap_is_multidrop(struct adiv5_dap *dap)
Check if SWD multidrop configuration is valid.
Definition: arm_adi_v5.h:756
#define ADIV5_DP_SELECT_APBANK
Definition: arm_adi_v5.h:101
#define DP_SELECT_DPBANK
Definition: arm_adi_v5.h:102
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:253
static int register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, const struct command_registration *cmds)
Register one or more commands in the specified context, as children of parent (or top-level commends,...
Definition: command.h:274
@ COMMAND_CONFIG
Definition: command.h:41
@ COMMAND_ANY
Definition: command.h:42
static enum reset_types jtag_reset_config
Definition: jtag/core.c:87
enum reset_types jtag_get_reset_config(void)
Definition: jtag/core.c:1734
int adapter_assert_reset(void)
Definition: jtag/core.c:1879
reset_types
Definition: jtag.h:216
@ RESET_SRST_NO_GATING
Definition: jtag.h:225
@ RESET_CNCT_UNDER_SRST
Definition: jtag.h:226
void alive_sleep(uint64_t ms)
Definition: log.c:456
#define ERROR_WAIT
Definition: log.h:171
#define LOG_DEBUG_IO(expr ...)
Definition: log.h:101
#define LOG_WARNING(expr ...)
Definition: log.h:129
#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
struct qn908x_flash_bank __attribute__
Definition: armv8.c:1016
Represents a driver for a debugging interface.
Definition: interface.h:207
const struct swd_driver * swd_ops
Low-level SWD APIs.
Definition: interface.h:345
This represents an ARM Debug Interface (v5) Access Port (AP).
Definition: arm_adi_v5.h:250
uint64_t ap_num
ADIv5: Number of this AP (0~255) ADIv6: Base address of this AP (4k aligned) TODO: to be more coheren...
Definition: arm_adi_v5.h:261
struct adiv5_dap * dap
DAP this AP belongs to.
Definition: arm_adi_v5.h:254
uint32_t memaccess_tck
Configures how many extra tck clocks are added after starting a MEM-AP access before we try to read i...
Definition: arm_adi_v5.h:306
This represents an ARM Debug Interface (v5) Debug Access Port (DAP).
Definition: arm_adi_v5.h:348
bool select_valid
Validity of DP SELECT cache.
Definition: arm_adi_v5.h:372
bool select1_valid
Definition: arm_adi_v5.h:373
struct adiv5_ap ap[DP_APSEL_MAX+1]
Definition: arm_adi_v5.h:364
bool select_dpbanksel_valid
Partial DPBANKSEL validity for SWD only.
Definition: arm_adi_v5.h:383
bool do_reconnect
Signals that an attempt to reestablish communication afresh should be performed before the next acces...
Definition: arm_adi_v5.h:414
uint32_t * last_read
Holds the pointer to the destination word for the last queued read, for use with posted AP read seque...
Definition: arm_adi_v5.h:392
bool switch_through_dormant
Record if enter in SWD required passing through DORMANT.
Definition: arm_adi_v5.h:430
uint32_t multidrop_targetsel
Value to select DP in SWD multidrop mode or DP_TARGETSEL_INVALID.
Definition: arm_adi_v5.h:421
uint64_t select
Cache for DP SELECT and SELECT1 (ADIv6) register.
Definition: arm_adi_v5.h:370
unsigned int asize
Definition: arm_adi_v5.h:436
const char * name
Definition: command.h:235
const char * usage
a string listing the options and arguments, required or optional
Definition: command.h:241
Transport-neutral representation of queued DAP transactions, supporting both JTAG and SWD transports.
Definition: arm_adi_v5.h:446
int(* pre_connect_init)(struct adiv5_dap *dap)
Optional; called once on the first enabled dap before connecting.
Definition: arm_adi_v5.h:448
Definition: register.h:111
int(* switch_seq)(enum swd_special_seq seq)
Queue a special SWDIO sequence.
Definition: swd.h:264
void(* read_reg)(uint8_t cmd, uint32_t *value, uint32_t ap_delay_hint)
Queued read of an AP or DP register.
Definition: swd.h:274
int(* init)(void)
Initialize the debug link so it can perform SWD operations.
Definition: swd.h:255
int(* run)(void)
Execute any queued transactions and collect the result.
Definition: swd.h:292
void(* write_reg)(uint8_t cmd, uint32_t value, uint32_t ap_delay_hint)
Queued write of an AP or DP register.
Definition: swd.h:284
Definition: psoc6.c:83
Wrapper for transport lifecycle operations.
Definition: transport.h:35
const char * name
Each transport has a unique name, used to select it from among the alternatives.
Definition: transport.h:41
static uint8_t swd_cmd(bool is_read, bool is_ap, uint8_t regnum)
Construct a "cmd" byte, in lSB bit order, which swd_driver.read_reg() and swd_driver....
Definition: swd.h:35
int64_t timeval_ms(void)
struct transport * get_current_transport(void)
Returns the transport currently being used by this debug or programming session.
Definition: transport.c:157
int transport_register(struct transport *new_transport)
Registers a transport.
Definition: transport.c:129
#define NULL
Definition: usb.h:16
uint8_t status[4]
Definition: vdebug.c:17