1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2016 by Matthias Welwarsky *
6 ***************************************************************************/
14 #include "target/arm_adi_v5.h"
15 #include "target/arm.h"
16 #include "helper/list.h"
17 #include "helper/command.h"
18 #include "transport/transport.h"
19 #include "jtag/interface.h"
21 static LIST_HEAD(all_dap
);
23 extern const struct dap_ops swd_dap_ops
;
24 extern const struct dap_ops jtag_dp_ops
;
25 extern struct adapter_driver
*adapter_driver
;
27 /* DAP command support */
28 struct arm_dap_object
{
32 const struct swd_driver
*swd
;
35 static void dap_instance_init(struct adiv5_dap
*dap
)
38 /* Set up with safe defaults */
39 for (i
= 0; i
<= DP_APSEL_MAX
; i
++) {
41 dap
->ap
[i
].ap_num
= DP_APSEL_INVALID
;
42 /* memaccess_tck max is 255 */
43 dap
->ap
[i
].memaccess_tck
= 255;
44 /* Number of bits for tar autoincrement, impl. dep. at least 10 */
45 dap
->ap
[i
].tar_autoincr_block
= (1<<10);
46 /* default CSW value */
47 dap
->ap
[i
].csw_default
= CSW_AHB_DEFAULT
;
48 dap
->ap
[i
].cfg_reg
= MEM_AP_REG_CFG_INVALID
; /* mem_ap configuration reg (large physical addr, etc.) */
49 dap
->ap
[i
].refcount
= 0;
50 dap
->ap
[i
].config_ap_never_release
= false;
52 INIT_LIST_HEAD(&dap
->cmd_journal
);
53 INIT_LIST_HEAD(&dap
->cmd_pool
);
56 const char *adiv5_dap_name(struct adiv5_dap
*self
)
58 struct arm_dap_object
*obj
= container_of(self
, struct arm_dap_object
, dap
);
62 const struct swd_driver
*adiv5_dap_swd_driver(struct adiv5_dap
*self
)
64 struct arm_dap_object
*obj
= container_of(self
, struct arm_dap_object
, dap
);
68 struct adiv5_dap
*adiv5_get_dap(struct arm_dap_object
*obj
)
72 struct adiv5_dap
*dap_instance_by_jim_obj(Jim_Interp
*interp
, Jim_Obj
*o
)
74 struct arm_dap_object
*obj
= NULL
;
78 name
= Jim_GetString(o
, NULL
);
80 list_for_each_entry(obj
, &all_dap
, lh
) {
81 if (!strcmp(name
, obj
->name
)) {
92 static int dap_init_all(void)
94 struct arm_dap_object
*obj
;
97 LOG_DEBUG("Initializing all DAPs ...");
99 list_for_each_entry(obj
, &all_dap
, lh
) {
100 struct adiv5_dap
*dap
= &obj
->dap
;
102 /* with hla, dap is just a dummy */
103 if (transport_is_hla())
106 /* skip taps that are disabled */
107 if (!dap
->tap
->enabled
)
110 if (transport_is_swd()) {
111 dap
->ops
= &swd_dap_ops
;
112 obj
->swd
= adapter_driver
->swd_ops
;
113 } else if (transport_is_dapdirect_swd()) {
114 dap
->ops
= adapter_driver
->dap_swd_ops
;
115 } else if (transport_is_dapdirect_jtag()) {
116 dap
->ops
= adapter_driver
->dap_jtag_ops
;
118 dap
->ops
= &jtag_dp_ops
;
120 if (dap
->adi_version
== 0) {
121 LOG_DEBUG("DAP %s configured by default to use ADIv5 protocol", jtag_tap_name(dap
->tap
));
122 dap
->adi_version
= 5;
124 LOG_DEBUG("DAP %s configured to use %s protocol by user cfg file", jtag_tap_name(dap
->tap
),
125 is_adiv6(dap
) ? "ADIv6" : "ADIv5");
128 retval
= dap
->ops
->connect(dap
);
129 if (retval
!= ERROR_OK
)
132 /* see if address size of ROM Table is greater than 32-bits */
136 retval
= dap
->ops
->queue_dp_read(dap
, DP_DPIDR1
, &dpidr1
);
137 if (retval
!= ERROR_OK
) {
138 LOG_ERROR("DAP read of DPIDR1 failed...");
141 retval
= dap_run(dap
);
142 if (retval
!= ERROR_OK
) {
143 LOG_ERROR("DAP read of DPIDR1 failed...");
146 dap
->asize
= dpidr1
& DP_DPIDR1_ASIZE_MASK
;
153 int dap_cleanup_all(void)
155 struct arm_dap_object
*obj
, *tmp
;
156 struct adiv5_dap
*dap
;
158 list_for_each_entry_safe(obj
, tmp
, &all_dap
, lh
) {
160 for (unsigned int i
= 0; i
<= DP_APSEL_MAX
; i
++) {
161 if (dap
->ap
[i
].refcount
!= 0)
162 LOG_ERROR("BUG: refcount AP#%u still %u at exit", i
, dap
->ap
[i
].refcount
);
164 if (dap
->ops
&& dap
->ops
->quit
)
176 CFG_IGNORE_SYSPWRUPACK
,
183 static const struct jim_nvp nvp_config_opts
[] = {
184 { .name
= "-chain-position", .value
= CFG_CHAIN_POSITION
},
185 { .name
= "-ignore-syspwrupack", .value
= CFG_IGNORE_SYSPWRUPACK
},
186 { .name
= "-dp-id", .value
= CFG_DP_ID
},
187 { .name
= "-instance-id", .value
= CFG_INSTANCE_ID
},
188 { .name
= "-adiv6", .value
= CFG_ADIV6
},
189 { .name
= "-adiv5", .value
= CFG_ADIV5
},
190 { .name
= NULL
, .value
= -1 }
193 static int dap_configure(struct jim_getopt_info
*goi
, struct arm_dap_object
*dap
)
198 /* parse config ... */
199 while (goi
->argc
> 0) {
200 Jim_SetEmptyResult(goi
->interp
);
202 e
= jim_getopt_nvp(goi
, nvp_config_opts
, &n
);
204 jim_getopt_nvp_unknown(goi
, nvp_config_opts
, 0);
208 case CFG_CHAIN_POSITION
: {
210 e
= jim_getopt_obj(goi
, &o_t
);
214 struct jtag_tap
*tap
;
215 tap
= jtag_tap_by_jim_obj(goi
->interp
, o_t
);
217 Jim_SetResultString(goi
->interp
, "-chain-position is invalid", -1);
224 case CFG_IGNORE_SYSPWRUPACK
:
225 dap
->dap
.ignore_syspwrupack
= true;
229 e
= jim_getopt_wide(goi
, &w
);
231 Jim_SetResultFormatted(goi
->interp
,
232 "create %s: bad parameter %s",
236 if (w
< 0 || w
> DP_TARGETSEL_DPID_MASK
) {
237 Jim_SetResultFormatted(goi
->interp
,
238 "create %s: %s out of range",
242 dap
->dap
.multidrop_targetsel
=
243 (dap
->dap
.multidrop_targetsel
& DP_TARGETSEL_INSTANCEID_MASK
)
244 | (w
& DP_TARGETSEL_DPID_MASK
);
245 dap
->dap
.multidrop_dp_id_valid
= true;
248 case CFG_INSTANCE_ID
: {
250 e
= jim_getopt_wide(goi
, &w
);
252 Jim_SetResultFormatted(goi
->interp
,
253 "create %s: bad parameter %s",
257 if (w
< 0 || w
> 15) {
258 Jim_SetResultFormatted(goi
->interp
,
259 "create %s: %s out of range",
263 dap
->dap
.multidrop_targetsel
=
264 (dap
->dap
.multidrop_targetsel
& DP_TARGETSEL_DPID_MASK
)
265 | ((w
<< DP_TARGETSEL_INSTANCEID_SHIFT
) & DP_TARGETSEL_INSTANCEID_MASK
);
266 dap
->dap
.multidrop_instance_id_valid
= true;
270 dap
->dap
.adi_version
= 6;
273 dap
->dap
.adi_version
= 5;
283 static int dap_check_config(struct adiv5_dap
*dap
)
285 if (transport_is_jtag() || transport_is_dapdirect_jtag() || transport_is_hla())
288 struct arm_dap_object
*obj
;
289 bool new_multidrop
= dap_is_multidrop(dap
);
290 bool had_multidrop
= new_multidrop
;
291 uint32_t targetsel
= dap
->multidrop_targetsel
;
292 unsigned int non_multidrop_count
= had_multidrop
? 0 : 1;
294 list_for_each_entry(obj
, &all_dap
, lh
) {
295 struct adiv5_dap
*dap_it
= &obj
->dap
;
297 if (transport_is_swd()) {
298 if (dap_is_multidrop(dap_it
)) {
299 had_multidrop
= true;
300 if (new_multidrop
&& dap_it
->multidrop_targetsel
== targetsel
) {
301 uint32_t dp_id
= targetsel
& DP_TARGETSEL_DPID_MASK
;
302 uint32_t instance_id
= targetsel
>> DP_TARGETSEL_INSTANCEID_SHIFT
;
303 LOG_ERROR("%s and %s have the same multidrop selectors -dp-id 0x%08"
304 PRIx32
" and -instance-id 0x%" PRIx32
,
305 obj
->name
, adiv5_dap_name(dap
),
310 non_multidrop_count
++;
312 } else if (transport_is_dapdirect_swd()) {
313 non_multidrop_count
++;
317 if (non_multidrop_count
> 1) {
318 LOG_ERROR("Two or more SWD non multidrop DAPs are not supported");
321 if (had_multidrop
&& non_multidrop_count
) {
322 LOG_ERROR("Mixing of SWD multidrop DAPs and non multidrop DAPs is not supported");
329 static int dap_create(struct jim_getopt_info
*goi
)
331 struct command_context
*cmd_ctx
;
332 static struct arm_dap_object
*dap
;
338 cmd_ctx
= current_command_context(goi
->interp
);
342 Jim_WrongNumArgs(goi
->interp
, 1, goi
->argv
, "?name? ..options...");
346 jim_getopt_obj(goi
, &new_cmd
);
347 /* does this command exist? */
348 cmd
= Jim_GetCommand(goi
->interp
, new_cmd
, JIM_NONE
);
350 cp
= Jim_GetString(new_cmd
, NULL
);
351 Jim_SetResultFormatted(goi
->interp
, "Command: %s Exists", cp
);
356 dap
= calloc(1, sizeof(struct arm_dap_object
));
360 dap_instance_init(&dap
->dap
);
362 cp
= Jim_GetString(new_cmd
, NULL
);
363 dap
->name
= strdup(cp
);
365 e
= dap_configure(goi
, dap
);
370 Jim_SetResultString(goi
->interp
, "-chain-position required when creating DAP", -1);
375 e
= dap_check_config(&dap
->dap
);
381 struct command_registration dap_create_commands
[] = {
385 .help
= "dap instance command group",
387 .chain
= dap_instance_commands
,
389 COMMAND_REGISTRATION_DONE
392 /* don't expose the instance commands when using hla */
393 if (transport_is_hla())
394 dap_create_commands
[0].chain
= NULL
;
396 e
= register_commands_with_data(cmd_ctx
, NULL
, dap_create_commands
, dap
);
402 list_add_tail(&dap
->lh
, &all_dap
);
412 static int jim_dap_create(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
414 struct jim_getopt_info goi
;
415 jim_getopt_setup(&goi
, interp
, argc
- 1, argv
+ 1);
417 Jim_WrongNumArgs(goi
.interp
, goi
.argc
, goi
.argv
,
418 "<name> [<dap_options> ...]");
421 return dap_create(&goi
);
424 static int jim_dap_names(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
426 struct arm_dap_object
*obj
;
429 Jim_WrongNumArgs(interp
, 1, argv
, "Too many parameters");
432 Jim_SetResult(interp
, Jim_NewListObj(interp
, NULL
, 0));
433 list_for_each_entry(obj
, &all_dap
, lh
) {
434 Jim_ListAppendElement(interp
, Jim_GetResult(interp
),
435 Jim_NewStringObj(interp
, obj
->name
, -1));
440 COMMAND_HANDLER(handle_dap_init
)
442 return dap_init_all();
445 COMMAND_HANDLER(handle_dap_info_command
)
447 struct target
*target
= get_current_target(CMD_CTX
);
448 struct arm
*arm
= target_to_arm(target
);
449 struct adiv5_dap
*dap
= arm
->dap
;
453 LOG_ERROR("DAP instance not available. Probably a HLA target...");
454 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
462 if (!strcmp(CMD_ARGV
[0], "root")) {
463 if (!is_adiv6(dap
)) {
464 command_print(CMD
, "Option \"root\" not allowed with ADIv5 DAP");
465 return ERROR_COMMAND_ARGUMENT_INVALID
;
467 int retval
= adiv6_dap_read_baseptr(CMD
, dap
, &apsel
);
468 if (retval
!= ERROR_OK
) {
469 command_print(CMD
, "Failed reading DAP baseptr");
474 COMMAND_PARSE_NUMBER(u64
, CMD_ARGV
[0], apsel
);
475 if (!is_ap_num_valid(dap
, apsel
))
476 return ERROR_COMMAND_SYNTAX_ERROR
;
479 return ERROR_COMMAND_SYNTAX_ERROR
;
482 struct adiv5_ap
*ap
= dap_get_ap(dap
, apsel
);
484 command_print(CMD
, "Cannot get AP");
487 int retval
= dap_info_command(CMD
, ap
);
492 static const struct command_registration dap_subcommand_handlers
[] = {
496 .jim_handler
= jim_dap_create
,
497 .usage
= "name '-chain-position' name",
498 .help
= "Creates a new DAP instance",
503 .jim_handler
= jim_dap_names
,
505 .help
= "Lists all registered DAP instances by name",
510 .handler
= handle_dap_init
,
512 .help
= "Initialize all registered DAP instances"
516 .handler
= handle_dap_info_command
,
517 .mode
= COMMAND_EXEC
,
518 .help
= "display ROM table for specified MEM-AP (default MEM-AP of current target) "
519 "or the ADIv6 root ROM table of current target's DAP",
520 .usage
= "[ap_num | 'root']",
522 COMMAND_REGISTRATION_DONE
525 static const struct command_registration dap_commands
[] = {
528 .mode
= COMMAND_CONFIG
,
529 .help
= "DAP commands",
530 .chain
= dap_subcommand_handlers
,
533 COMMAND_REGISTRATION_DONE
536 int dap_register_commands(struct command_context
*cmd_ctx
)
538 return register_commands(cmd_ctx
, NULL
, dap_commands
);