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  int retval = swd_check_reconnect(dap);
506  if (retval != ERROR_OK)
507  return retval;
508 
509  retval = swd_multidrop_select(dap);
510  if (retval != ERROR_OK)
511  return retval;
512 
513  return swd_queue_dp_write_inner(dap, reg, data);
514 }
515 
517 static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned int reg)
518 {
519  int retval;
520  struct adiv5_dap *dap = ap->dap;
521  uint64_t sel;
522 
523  if (is_adiv6(dap))
524  sel = ap->ap_num | (reg & 0x00000FF0);
525  else
526  sel = (ap->ap_num << 24) | (reg & ADIV5_DP_SELECT_APBANK);
527 
528  uint64_t sel_diff = (sel ^ dap->select) & SELECT_AP_MASK;
529 
530  bool set_select = !dap->select_valid || (sel_diff & 0xffffffffull);
531  bool set_select1 = is_adiv6(dap) && dap->asize > 32
532  && (!dap->select1_valid
533  || sel_diff & (0xffffffffull << 32));
534 
535  if (set_select && set_select1) {
536  /* Prepare DP bank for DP_SELECT1 now to save one write */
537  sel |= (DP_SELECT1 & 0x000000f0) >> 4;
538  } else {
539  /* Use the DP part of dap->select regardless of dap->select_valid:
540  * if !dap->select_valid
541  * dap->select contains a speculative value likely going to be used
542  * in the following swd_queue_dp_bankselect().
543  * Moreover dap->select_valid should never be false here as a DP bank
544  * is always selected before selecting an AP bank */
545  sel |= dap->select & DP_SELECT_DPBANK;
546  }
547 
548  if (set_select) {
549  LOG_DEBUG_IO("AP BANK SELECT: %" PRIx32, (uint32_t)sel);
550 
551  retval = swd_queue_dp_write(dap, DP_SELECT, (uint32_t)sel);
552  if (retval != ERROR_OK)
553  return retval;
554  }
555 
556  if (set_select1) {
557  LOG_DEBUG_IO("AP BANK SELECT1: %" PRIx32, (uint32_t)(sel >> 32));
558 
559  retval = swd_queue_dp_write(dap, DP_SELECT1, (uint32_t)(sel >> 32));
560  if (retval != ERROR_OK)
561  return retval;
562  }
563 
564  return ERROR_OK;
565 }
566 
567 static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned int reg,
568  uint32_t *data)
569 {
570  struct adiv5_dap *dap = ap->dap;
571  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
572  assert(swd);
573 
574  int retval = swd_check_reconnect(dap);
575  if (retval != ERROR_OK)
576  return retval;
577 
578  retval = swd_multidrop_select(dap);
579  if (retval != ERROR_OK)
580  return retval;
581 
582  retval = swd_queue_ap_bankselect(ap, reg);
583  if (retval != ERROR_OK)
584  return retval;
585 
586  swd->read_reg(swd_cmd(true, true, reg), dap->last_read, ap->memaccess_tck);
587  dap->last_read = data;
588 
589  return check_sync(dap);
590 }
591 
592 static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned int reg,
593  uint32_t data)
594 {
595  struct adiv5_dap *dap = ap->dap;
596  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
597  assert(swd);
598 
599  int retval = swd_check_reconnect(dap);
600  if (retval != ERROR_OK)
601  return retval;
602 
603  retval = swd_multidrop_select(dap);
604  if (retval != ERROR_OK)
605  return retval;
606 
607  swd_finish_read(dap);
608 
609  retval = swd_queue_ap_bankselect(ap, reg);
610  if (retval != ERROR_OK)
611  return retval;
612 
613  swd->write_reg(swd_cmd(false, true, reg), data, ap->memaccess_tck);
614 
615  return check_sync(dap);
616 }
617 
619 static int swd_run(struct adiv5_dap *dap)
620 {
621  int retval = swd_multidrop_select(dap);
622  if (retval != ERROR_OK)
623  return retval;
624 
625  swd_finish_read(dap);
626 
627  retval = swd_run_inner(dap);
628  if (retval != ERROR_OK) {
629  /* fault response */
630  dap->do_reconnect = true;
631  }
632 
633  return retval;
634 }
635 
637 static void swd_quit(struct adiv5_dap *dap)
638 {
639  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
640  static bool done;
641 
642  /* There is no difference if the sequence is sent at the last
643  * or the first swd_quit() call, send it just once */
644  if (done)
645  return;
646 
647  done = true;
648  if (dap_is_multidrop(dap)) {
649  /* Emit the switch seq to dormant state regardless the state mirrored
650  * in swd_multidrop_in_swd_state. Doing so ensures robust operation
651  * in the case the variable is out of sync.
652  * Sending SWD_TO_DORMANT makes no change if the DP is already dormant. */
655  /* Revisit!
656  * Leaving DPs in dormant state was tested and offers some safety
657  * against DPs mismatch in case of unintentional use of non-multidrop SWD.
658  * To put SWJ-DPs to power-on state issue
659  * swd->switch_seq(DORMANT_TO_JTAG);
660  */
661  } else {
662  if (dap->switch_through_dormant) {
665  } else {
666  swd->switch_seq(SWD_TO_JTAG);
667  }
668  }
669 
670  /* flush the queue to shift out the sequence before exit */
671  swd->run();
672 }
673 
674 const struct dap_ops swd_dap_ops = {
676  .connect = swd_connect,
677  .send_sequence = swd_send_sequence,
678  .queue_dp_read = swd_queue_dp_read,
679  .queue_dp_write = swd_queue_dp_write,
680  .queue_ap_read = swd_queue_ap_read,
681  .queue_ap_write = swd_queue_ap_write,
682  .queue_ap_abort = swd_queue_ap_abort,
683  .run = swd_run,
684  .quit = swd_quit,
685 };
686 
687 static const struct command_registration swd_commands[] = {
688  {
689  /*
690  * Set up SWD and JTAG targets identically, unless/until
691  * infrastructure improves ... meanwhile, ignore all
692  * JTAG-specific stuff like IR length for SWD.
693  *
694  * REVISIT can we verify "just one SWD DAP" here/early?
695  */
696  .name = "newdap",
697  .handler = handle_jtag_newtap,
698  .mode = COMMAND_CONFIG,
699  .help = "declare a new SWD DAP",
700  .usage = "basename dap_type ['-irlen' count] "
701  "['-enable'|'-disable'] "
702  "['-expected_id' number] "
703  "['-ignore-version'] "
704  "['-ignore-bypass'] "
705  "['-ircapture' number] "
706  "['-ir-bypass' number] "
707  "['-mask' number]",
708  },
710 };
711 
712 static const struct command_registration swd_handlers[] = {
713  {
714  .name = "swd",
715  .mode = COMMAND_ANY,
716  .help = "SWD command group",
717  .chain = swd_commands,
718  .usage = "",
719  },
721 };
722 
723 static int swd_select(struct command_context *ctx)
724 {
725  /* FIXME: only place where global 'adapter_driver' is still needed */
726  extern struct adapter_driver *adapter_driver;
727  const struct swd_driver *swd = adapter_driver->swd_ops;
728  int retval;
729 
730  retval = register_commands(ctx, NULL, swd_handlers);
731  if (retval != ERROR_OK)
732  return retval;
733 
734  /* be sure driver is in SWD mode; start
735  * with hardware default TRN (1), it can be changed later
736  */
737  if (!swd || !swd->read_reg || !swd->write_reg || !swd->init) {
738  LOG_DEBUG("no SWD driver?");
739  return ERROR_FAIL;
740  }
741 
742  retval = swd->init();
743  if (retval != ERROR_OK) {
744  LOG_DEBUG("can't init SWD driver");
745  return retval;
746  }
747 
748  return retval;
749 }
750 
751 static int swd_init(struct command_context *ctx)
752 {
753  /* nothing done here, SWD is initialized
754  * together with the DAP */
755  return ERROR_OK;
756 }
757 
758 static struct transport swd_transport = {
759  .name = "swd",
760  .select = swd_select,
761  .init = swd_init,
762 };
763 
764 static void swd_constructor(void) __attribute__((constructor));
765 static void swd_constructor(void)
766 {
768 }
769 
774 {
776 }
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:674
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:687
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:567
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:751
static int swd_run(struct adiv5_dap *dap)
Executes all queued DAP operations.
Definition: adi_v5_swd.c:619
static int swd_select(struct command_context *ctx)
Definition: adi_v5_swd.c:723
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:517
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:758
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:773
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:592
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:637
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:712
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:764
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:89
enum reset_types jtag_get_reset_config(void)
Definition: jtag/core.c:1747
int adapter_assert_reset(void)
Definition: jtag/core.c:1892
reset_types
Definition: jtag.h:215
@ RESET_SRST_NO_GATING
Definition: jtag.h:224
@ RESET_CNCT_UNDER_SRST
Definition: jtag.h:225
void alive_sleep(uint64_t ms)
Definition: log.c:467
#define ERROR_WAIT
Definition: log.h:175
#define LOG_DEBUG_IO(expr ...)
Definition: log.h:102
#define LOG_WARNING(expr ...)
Definition: log.h:130
#define ERROR_FAIL
Definition: log.h:174
#define LOG_ERROR(expr ...)
Definition: log.h:133
#define LOG_INFO(expr ...)
Definition: log.h:127
#define LOG_DEBUG(expr ...)
Definition: log.h:110
#define ERROR_OK
Definition: log.h:168
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