openocd: fix SPDX tag format for files .c
[fw/openocd] / src / target / arm_dap.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4  *   Copyright (C) 2016 by Matthias Welwarsky                              *
5  *                                                                         *
6  ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <stdlib.h>
13 #include <stdint.h>
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"
20
21 static LIST_HEAD(all_dap);
22
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;
26
27 /* DAP command support */
28 struct arm_dap_object {
29         struct list_head lh;
30         struct adiv5_dap dap;
31         char *name;
32         const struct swd_driver *swd;
33 };
34
35 static void dap_instance_init(struct adiv5_dap *dap)
36 {
37         int i;
38         /* Set up with safe defaults */
39         for (i = 0; i <= DP_APSEL_MAX; i++) {
40                 dap->ap[i].dap = dap;
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;
51         }
52         INIT_LIST_HEAD(&dap->cmd_journal);
53         INIT_LIST_HEAD(&dap->cmd_pool);
54 }
55
56 const char *adiv5_dap_name(struct adiv5_dap *self)
57 {
58         struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
59         return obj->name;
60 }
61
62 const struct swd_driver *adiv5_dap_swd_driver(struct adiv5_dap *self)
63 {
64         struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
65         return obj->swd;
66 }
67
68 struct adiv5_dap *adiv5_get_dap(struct arm_dap_object *obj)
69 {
70         return &obj->dap;
71 }
72 struct adiv5_dap *dap_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
73 {
74         struct arm_dap_object *obj = NULL;
75         const char *name;
76         bool found = false;
77
78         name = Jim_GetString(o, NULL);
79
80         list_for_each_entry(obj, &all_dap, lh) {
81                 if (!strcmp(name, obj->name)) {
82                         found = true;
83                         break;
84                 }
85         }
86
87         if (found)
88                 return &obj->dap;
89         return NULL;
90 }
91
92 static int dap_init_all(void)
93 {
94         struct arm_dap_object *obj;
95         int retval;
96
97         LOG_DEBUG("Initializing all DAPs ...");
98
99         list_for_each_entry(obj, &all_dap, lh) {
100                 struct adiv5_dap *dap = &obj->dap;
101
102                 /* with hla, dap is just a dummy */
103                 if (transport_is_hla())
104                         continue;
105
106                 /* skip taps that are disabled */
107                 if (!dap->tap->enabled)
108                         continue;
109
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;
117                 } else
118                         dap->ops = &jtag_dp_ops;
119
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;
123                 } else {
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");
126                 }
127
128                 retval = dap->ops->connect(dap);
129                 if (retval != ERROR_OK)
130                         return retval;
131
132                 /* see if address size of ROM Table is greater than 32-bits */
133                 if (is_adiv6(dap)) {
134                         uint32_t dpidr1;
135
136                         retval = dap->ops->queue_dp_read(dap, DP_DPIDR1, &dpidr1);
137                         if (retval != ERROR_OK) {
138                                 LOG_ERROR("DAP read of DPIDR1 failed...");
139                                 return retval;
140                         }
141                         retval = dap_run(dap);
142                         if (retval != ERROR_OK) {
143                                 LOG_ERROR("DAP read of DPIDR1 failed...");
144                                 return retval;
145                         }
146                         dap->asize = dpidr1 & DP_DPIDR1_ASIZE_MASK;
147                 }
148         }
149
150         return ERROR_OK;
151 }
152
153 int dap_cleanup_all(void)
154 {
155         struct arm_dap_object *obj, *tmp;
156         struct adiv5_dap *dap;
157
158         list_for_each_entry_safe(obj, tmp, &all_dap, lh) {
159                 dap = &obj->dap;
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);
163                 }
164                 if (dap->ops && dap->ops->quit)
165                         dap->ops->quit(dap);
166
167                 free(obj->name);
168                 free(obj);
169         }
170
171         return ERROR_OK;
172 }
173
174 enum dap_cfg_param {
175         CFG_CHAIN_POSITION,
176         CFG_IGNORE_SYSPWRUPACK,
177         CFG_DP_ID,
178         CFG_INSTANCE_ID,
179         CFG_ADIV6,
180         CFG_ADIV5,
181 };
182
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 }
191 };
192
193 static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap)
194 {
195         struct jim_nvp *n;
196         int e;
197
198         /* parse config ... */
199         while (goi->argc > 0) {
200                 Jim_SetEmptyResult(goi->interp);
201
202                 e = jim_getopt_nvp(goi, nvp_config_opts, &n);
203                 if (e != JIM_OK) {
204                         jim_getopt_nvp_unknown(goi, nvp_config_opts, 0);
205                         return e;
206                 }
207                 switch (n->value) {
208                 case CFG_CHAIN_POSITION: {
209                         Jim_Obj *o_t;
210                         e = jim_getopt_obj(goi, &o_t);
211                         if (e != JIM_OK)
212                                 return e;
213
214                         struct jtag_tap *tap;
215                         tap = jtag_tap_by_jim_obj(goi->interp, o_t);
216                         if (!tap) {
217                                 Jim_SetResultString(goi->interp, "-chain-position is invalid", -1);
218                                 return JIM_ERR;
219                         }
220                         dap->dap.tap = tap;
221                         /* loop for more */
222                         break;
223                 }
224                 case CFG_IGNORE_SYSPWRUPACK:
225                         dap->dap.ignore_syspwrupack = true;
226                         break;
227                 case CFG_DP_ID: {
228                         jim_wide w;
229                         e = jim_getopt_wide(goi, &w);
230                         if (e != JIM_OK) {
231                                 Jim_SetResultFormatted(goi->interp,
232                                                 "create %s: bad parameter %s",
233                                                 dap->name, n->name);
234                                 return JIM_ERR;
235                         }
236                         if (w < 0 || w > DP_TARGETSEL_DPID_MASK) {
237                                 Jim_SetResultFormatted(goi->interp,
238                                                 "create %s: %s out of range",
239                                                 dap->name, n->name);
240                                 return JIM_ERR;
241                         }
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;
246                         break;
247                 }
248                 case CFG_INSTANCE_ID: {
249                         jim_wide w;
250                         e = jim_getopt_wide(goi, &w);
251                         if (e != JIM_OK) {
252                                 Jim_SetResultFormatted(goi->interp,
253                                                 "create %s: bad parameter %s",
254                                                 dap->name, n->name);
255                                 return JIM_ERR;
256                         }
257                         if (w < 0 || w > 15) {
258                                 Jim_SetResultFormatted(goi->interp,
259                                                 "create %s: %s out of range",
260                                                 dap->name, n->name);
261                                 return JIM_ERR;
262                         }
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;
267                         break;
268                 }
269                 case CFG_ADIV6:
270                         dap->dap.adi_version = 6;
271                         break;
272                 case CFG_ADIV5:
273                         dap->dap.adi_version = 5;
274                         break;
275                 default:
276                         break;
277                 }
278         }
279
280         return JIM_OK;
281 }
282
283 static int dap_check_config(struct adiv5_dap *dap)
284 {
285         if (transport_is_jtag() || transport_is_dapdirect_jtag() || transport_is_hla())
286                 return ERROR_OK;
287
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;
293
294         list_for_each_entry(obj, &all_dap, lh) {
295                 struct adiv5_dap *dap_it = &obj->dap;
296
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),
306                                                           dp_id, instance_id);
307                                         return ERROR_FAIL;
308                                 }
309                         } else {
310                                 non_multidrop_count++;
311                         }
312                 } else if (transport_is_dapdirect_swd()) {
313                         non_multidrop_count++;
314                 }
315         }
316
317         if (non_multidrop_count > 1) {
318                 LOG_ERROR("Two or more SWD non multidrop DAPs are not supported");
319                 return ERROR_FAIL;
320         }
321         if (had_multidrop && non_multidrop_count) {
322                 LOG_ERROR("Mixing of SWD multidrop DAPs and non multidrop DAPs is not supported");
323                 return ERROR_FAIL;
324         }
325
326         return ERROR_OK;
327 }
328
329 static int dap_create(struct jim_getopt_info *goi)
330 {
331         struct command_context *cmd_ctx;
332         static struct arm_dap_object *dap;
333         Jim_Obj *new_cmd;
334         Jim_Cmd *cmd;
335         const char *cp;
336         int e;
337
338         cmd_ctx = current_command_context(goi->interp);
339         assert(cmd_ctx);
340
341         if (goi->argc < 3) {
342                 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
343                 return JIM_ERR;
344         }
345         /* COMMAND */
346         jim_getopt_obj(goi, &new_cmd);
347         /* does this command exist? */
348         cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
349         if (cmd) {
350                 cp = Jim_GetString(new_cmd, NULL);
351                 Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
352                 return JIM_ERR;
353         }
354
355         /* Create it */
356         dap = calloc(1, sizeof(struct arm_dap_object));
357         if (!dap)
358                 return JIM_ERR;
359
360         dap_instance_init(&dap->dap);
361
362         cp = Jim_GetString(new_cmd, NULL);
363         dap->name = strdup(cp);
364
365         e = dap_configure(goi, dap);
366         if (e != JIM_OK)
367                 goto err;
368
369         if (!dap->dap.tap) {
370                 Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1);
371                 e = JIM_ERR;
372                 goto err;
373         }
374
375         e = dap_check_config(&dap->dap);
376         if (e != ERROR_OK) {
377                 e = JIM_ERR;
378                 goto err;
379         }
380
381         struct command_registration dap_create_commands[] = {
382                 {
383                         .name = cp,
384                         .mode = COMMAND_ANY,
385                         .help = "dap instance command group",
386                         .usage = "",
387                         .chain = dap_instance_commands,
388                 },
389                 COMMAND_REGISTRATION_DONE
390         };
391
392         /* don't expose the instance commands when using hla */
393         if (transport_is_hla())
394                 dap_create_commands[0].chain = NULL;
395
396         e = register_commands_with_data(cmd_ctx, NULL, dap_create_commands, dap);
397         if (e != ERROR_OK) {
398                 e = JIM_ERR;
399                 goto err;
400         }
401
402         list_add_tail(&dap->lh, &all_dap);
403
404         return JIM_OK;
405
406 err:
407         free(dap->name);
408         free(dap);
409         return e;
410 }
411
412 static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
413 {
414         struct jim_getopt_info goi;
415         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
416         if (goi.argc < 2) {
417                 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
418                         "<name> [<dap_options> ...]");
419                 return JIM_ERR;
420         }
421         return dap_create(&goi);
422 }
423
424 static int jim_dap_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
425 {
426         struct arm_dap_object *obj;
427
428         if (argc != 1) {
429                 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
430                 return JIM_ERR;
431         }
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));
436         }
437         return JIM_OK;
438 }
439
440 COMMAND_HANDLER(handle_dap_init)
441 {
442         return dap_init_all();
443 }
444
445 COMMAND_HANDLER(handle_dap_info_command)
446 {
447         struct target *target = get_current_target(CMD_CTX);
448         struct arm *arm = target_to_arm(target);
449         struct adiv5_dap *dap = arm->dap;
450         uint64_t apsel;
451
452         if (!dap) {
453                 LOG_ERROR("DAP instance not available. Probably a HLA target...");
454                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
455         }
456
457         switch (CMD_ARGC) {
458                 case 0:
459                         apsel = dap->apsel;
460                         break;
461                 case 1:
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;
466                                 }
467                                 int retval = adiv6_dap_read_baseptr(CMD, dap, &apsel);
468                                 if (retval != ERROR_OK) {
469                                         command_print(CMD, "Failed reading DAP baseptr");
470                                         return retval;
471                                 }
472                                 break;
473                         }
474                         COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], apsel);
475                         if (!is_ap_num_valid(dap, apsel))
476                                 return ERROR_COMMAND_SYNTAX_ERROR;
477                         break;
478                 default:
479                         return ERROR_COMMAND_SYNTAX_ERROR;
480         }
481
482         struct adiv5_ap *ap = dap_get_ap(dap, apsel);
483         if (!ap) {
484                 command_print(CMD, "Cannot get AP");
485                 return ERROR_FAIL;
486         }
487         int retval = dap_info_command(CMD, ap);
488         dap_put_ap(ap);
489         return retval;
490 }
491
492 static const struct command_registration dap_subcommand_handlers[] = {
493         {
494                 .name = "create",
495                 .mode = COMMAND_ANY,
496                 .jim_handler = jim_dap_create,
497                 .usage = "name '-chain-position' name",
498                 .help = "Creates a new DAP instance",
499         },
500         {
501                 .name = "names",
502                 .mode = COMMAND_ANY,
503                 .jim_handler = jim_dap_names,
504                 .usage = "",
505                 .help = "Lists all registered DAP instances by name",
506         },
507         {
508                 .name = "init",
509                 .mode = COMMAND_ANY,
510                 .handler = handle_dap_init,
511                 .usage = "",
512                 .help = "Initialize all registered DAP instances"
513         },
514         {
515                 .name = "info",
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']",
521         },
522         COMMAND_REGISTRATION_DONE
523 };
524
525 static const struct command_registration dap_commands[] = {
526         {
527                 .name = "dap",
528                 .mode = COMMAND_CONFIG,
529                 .help = "DAP commands",
530                 .chain = dap_subcommand_handlers,
531                 .usage = "",
532         },
533         COMMAND_REGISTRATION_DONE
534 };
535
536 int dap_register_commands(struct command_context *cmd_ctx)
537 {
538         return register_commands(cmd_ctx, NULL, dap_commands);
539 }