adiv6: use struct adiv5_ap->ap_num to contain the AP base address
[fw/openocd] / src / target / arm_dap.c
1 /***************************************************************************
2  *   Copyright (C) 2016 by Matthias Welwarsky                              *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *                                                                         *
18  ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include "target/arm_adi_v5.h"
27 #include "target/arm.h"
28 #include "helper/list.h"
29 #include "helper/command.h"
30 #include "transport/transport.h"
31 #include "jtag/interface.h"
32
33 static LIST_HEAD(all_dap);
34
35 extern const struct dap_ops swd_dap_ops;
36 extern const struct dap_ops jtag_dp_ops;
37 extern struct adapter_driver *adapter_driver;
38
39 /* DAP command support */
40 struct arm_dap_object {
41         struct list_head lh;
42         struct adiv5_dap dap;
43         char *name;
44         const struct swd_driver *swd;
45 };
46
47 static void dap_instance_init(struct adiv5_dap *dap)
48 {
49         int i;
50         /* Set up with safe defaults */
51         for (i = 0; i <= DP_APSEL_MAX; i++) {
52                 dap->ap[i].dap = dap;
53                 dap->ap[i].ap_num = DP_APSEL_INVALID;
54                 /* memaccess_tck max is 255 */
55                 dap->ap[i].memaccess_tck = 255;
56                 /* Number of bits for tar autoincrement, impl. dep. at least 10 */
57                 dap->ap[i].tar_autoincr_block = (1<<10);
58                 /* default CSW value */
59                 dap->ap[i].csw_default = CSW_AHB_DEFAULT;
60                 dap->ap[i].cfg_reg = MEM_AP_REG_CFG_INVALID; /* mem_ap configuration reg (large physical addr, etc.) */
61                 dap->ap[i].refcount = 0;
62                 dap->ap[i].config_ap_never_release = false;
63         }
64         INIT_LIST_HEAD(&dap->cmd_journal);
65         INIT_LIST_HEAD(&dap->cmd_pool);
66 }
67
68 const char *adiv5_dap_name(struct adiv5_dap *self)
69 {
70         struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
71         return obj->name;
72 }
73
74 const struct swd_driver *adiv5_dap_swd_driver(struct adiv5_dap *self)
75 {
76         struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
77         return obj->swd;
78 }
79
80 struct adiv5_dap *adiv5_get_dap(struct arm_dap_object *obj)
81 {
82         return &obj->dap;
83 }
84 struct adiv5_dap *dap_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
85 {
86         struct arm_dap_object *obj = NULL;
87         const char *name;
88         bool found = false;
89
90         name = Jim_GetString(o, NULL);
91
92         list_for_each_entry(obj, &all_dap, lh) {
93                 if (!strcmp(name, obj->name)) {
94                         found = true;
95                         break;
96                 }
97         }
98
99         if (found)
100                 return &obj->dap;
101         return NULL;
102 }
103
104 static int dap_init_all(void)
105 {
106         struct arm_dap_object *obj;
107         int retval;
108
109         LOG_DEBUG("Initializing all DAPs ...");
110
111         list_for_each_entry(obj, &all_dap, lh) {
112                 struct adiv5_dap *dap = &obj->dap;
113
114                 /* with hla, dap is just a dummy */
115                 if (transport_is_hla())
116                         continue;
117
118                 /* skip taps that are disabled */
119                 if (!dap->tap->enabled)
120                         continue;
121
122                 if (transport_is_swd()) {
123                         dap->ops = &swd_dap_ops;
124                         obj->swd = adapter_driver->swd_ops;
125                 } else if (transport_is_dapdirect_swd()) {
126                         dap->ops = adapter_driver->dap_swd_ops;
127                 } else if (transport_is_dapdirect_jtag()) {
128                         dap->ops = adapter_driver->dap_jtag_ops;
129                 } else
130                         dap->ops = &jtag_dp_ops;
131
132                 if (dap->adi_version == 0) {
133                         LOG_DEBUG("DAP %s configured by default to use ADIv5 protocol", jtag_tap_name(dap->tap));
134                         dap->adi_version = 5;
135                 } else {
136                         LOG_DEBUG("DAP %s configured to use %s protocol by user cfg file", jtag_tap_name(dap->tap),
137                                 is_adiv6(dap) ? "ADIv6" : "ADIv5");
138                 }
139
140                 retval = dap->ops->connect(dap);
141                 if (retval != ERROR_OK)
142                         return retval;
143
144                 /* see if address size of ROM Table is greater than 32-bits */
145                 if (is_adiv6(dap)) {
146                         uint32_t dpidr1;
147
148                         retval = dap->ops->queue_dp_read(dap, DP_DPIDR1, &dpidr1);
149                         if (retval != ERROR_OK) {
150                                 LOG_ERROR("DAP read of DPIDR1 failed...");
151                                 return retval;
152                         }
153                         retval = dap_run(dap);
154                         if (retval != ERROR_OK) {
155                                 LOG_ERROR("DAP read of DPIDR1 failed...");
156                                 return retval;
157                         }
158                         dap->asize = dpidr1 & DP_DPIDR1_ASIZE_MASK;
159                 }
160         }
161
162         return ERROR_OK;
163 }
164
165 int dap_cleanup_all(void)
166 {
167         struct arm_dap_object *obj, *tmp;
168         struct adiv5_dap *dap;
169
170         list_for_each_entry_safe(obj, tmp, &all_dap, lh) {
171                 dap = &obj->dap;
172                 for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) {
173                         if (dap->ap[i].refcount != 0)
174                                 LOG_ERROR("BUG: refcount AP#%u still %u at exit", i, dap->ap[i].refcount);
175                 }
176                 if (dap->ops && dap->ops->quit)
177                         dap->ops->quit(dap);
178
179                 free(obj->name);
180                 free(obj);
181         }
182
183         return ERROR_OK;
184 }
185
186 enum dap_cfg_param {
187         CFG_CHAIN_POSITION,
188         CFG_IGNORE_SYSPWRUPACK,
189         CFG_DP_ID,
190         CFG_INSTANCE_ID,
191         CFG_ADIV6,
192         CFG_ADIV5,
193 };
194
195 static const struct jim_nvp nvp_config_opts[] = {
196         { .name = "-chain-position",     .value = CFG_CHAIN_POSITION },
197         { .name = "-ignore-syspwrupack", .value = CFG_IGNORE_SYSPWRUPACK },
198         { .name = "-dp-id",              .value = CFG_DP_ID },
199         { .name = "-instance-id",        .value = CFG_INSTANCE_ID },
200         { .name = "-adiv6",              .value = CFG_ADIV6 },
201         { .name = "-adiv5",              .value = CFG_ADIV5 },
202         { .name = NULL, .value = -1 }
203 };
204
205 static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap)
206 {
207         struct jim_nvp *n;
208         int e;
209
210         /* parse config ... */
211         while (goi->argc > 0) {
212                 Jim_SetEmptyResult(goi->interp);
213
214                 e = jim_getopt_nvp(goi, nvp_config_opts, &n);
215                 if (e != JIM_OK) {
216                         jim_getopt_nvp_unknown(goi, nvp_config_opts, 0);
217                         return e;
218                 }
219                 switch (n->value) {
220                 case CFG_CHAIN_POSITION: {
221                         Jim_Obj *o_t;
222                         e = jim_getopt_obj(goi, &o_t);
223                         if (e != JIM_OK)
224                                 return e;
225
226                         struct jtag_tap *tap;
227                         tap = jtag_tap_by_jim_obj(goi->interp, o_t);
228                         if (!tap) {
229                                 Jim_SetResultString(goi->interp, "-chain-position is invalid", -1);
230                                 return JIM_ERR;
231                         }
232                         dap->dap.tap = tap;
233                         /* loop for more */
234                         break;
235                 }
236                 case CFG_IGNORE_SYSPWRUPACK:
237                         dap->dap.ignore_syspwrupack = true;
238                         break;
239                 case CFG_DP_ID: {
240                         jim_wide w;
241                         e = jim_getopt_wide(goi, &w);
242                         if (e != JIM_OK) {
243                                 Jim_SetResultFormatted(goi->interp,
244                                                 "create %s: bad parameter %s",
245                                                 dap->name, n->name);
246                                 return JIM_ERR;
247                         }
248                         if (w < 0 || w > DP_TARGETSEL_DPID_MASK) {
249                                 Jim_SetResultFormatted(goi->interp,
250                                                 "create %s: %s out of range",
251                                                 dap->name, n->name);
252                                 return JIM_ERR;
253                         }
254                         dap->dap.multidrop_targetsel =
255                                 (dap->dap.multidrop_targetsel & DP_TARGETSEL_INSTANCEID_MASK)
256                                 | (w & DP_TARGETSEL_DPID_MASK);
257                         dap->dap.multidrop_dp_id_valid = true;
258                         break;
259                 }
260                 case CFG_INSTANCE_ID: {
261                         jim_wide w;
262                         e = jim_getopt_wide(goi, &w);
263                         if (e != JIM_OK) {
264                                 Jim_SetResultFormatted(goi->interp,
265                                                 "create %s: bad parameter %s",
266                                                 dap->name, n->name);
267                                 return JIM_ERR;
268                         }
269                         if (w < 0 || w > 15) {
270                                 Jim_SetResultFormatted(goi->interp,
271                                                 "create %s: %s out of range",
272                                                 dap->name, n->name);
273                                 return JIM_ERR;
274                         }
275                         dap->dap.multidrop_targetsel =
276                                 (dap->dap.multidrop_targetsel & DP_TARGETSEL_DPID_MASK)
277                                 | ((w << DP_TARGETSEL_INSTANCEID_SHIFT) & DP_TARGETSEL_INSTANCEID_MASK);
278                         dap->dap.multidrop_instance_id_valid = true;
279                         break;
280                 }
281                 case CFG_ADIV6:
282                         dap->dap.adi_version = 6;
283                         break;
284                 case CFG_ADIV5:
285                         dap->dap.adi_version = 5;
286                         break;
287                 default:
288                         break;
289                 }
290         }
291
292         return JIM_OK;
293 }
294
295 static int dap_check_config(struct adiv5_dap *dap)
296 {
297         if (transport_is_jtag() || transport_is_dapdirect_jtag() || transport_is_hla())
298                 return ERROR_OK;
299
300         struct arm_dap_object *obj;
301         bool new_multidrop = dap_is_multidrop(dap);
302         bool had_multidrop = new_multidrop;
303         uint32_t targetsel = dap->multidrop_targetsel;
304         unsigned int non_multidrop_count = had_multidrop ? 0 : 1;
305
306         list_for_each_entry(obj, &all_dap, lh) {
307                 struct adiv5_dap *dap_it = &obj->dap;
308
309                 if (transport_is_swd()) {
310                         if (dap_is_multidrop(dap_it)) {
311                                 had_multidrop = true;
312                                 if (new_multidrop && dap_it->multidrop_targetsel == targetsel) {
313                                         uint32_t dp_id = targetsel & DP_TARGETSEL_DPID_MASK;
314                                         uint32_t instance_id = targetsel >> DP_TARGETSEL_INSTANCEID_SHIFT;
315                                         LOG_ERROR("%s and %s have the same multidrop selectors -dp-id 0x%08"
316                                                           PRIx32 " and -instance-id 0x%" PRIx32,
317                                                           obj->name, adiv5_dap_name(dap),
318                                                           dp_id, instance_id);
319                                         return ERROR_FAIL;
320                                 }
321                         } else {
322                                 non_multidrop_count++;
323                         }
324                 } else if (transport_is_dapdirect_swd()) {
325                         non_multidrop_count++;
326                 }
327         }
328
329         if (non_multidrop_count > 1) {
330                 LOG_ERROR("Two or more SWD non multidrop DAPs are not supported");
331                 return ERROR_FAIL;
332         }
333         if (had_multidrop && non_multidrop_count) {
334                 LOG_ERROR("Mixing of SWD multidrop DAPs and non multidrop DAPs is not supported");
335                 return ERROR_FAIL;
336         }
337
338         return ERROR_OK;
339 }
340
341 static int dap_create(struct jim_getopt_info *goi)
342 {
343         struct command_context *cmd_ctx;
344         static struct arm_dap_object *dap;
345         Jim_Obj *new_cmd;
346         Jim_Cmd *cmd;
347         const char *cp;
348         int e;
349
350         cmd_ctx = current_command_context(goi->interp);
351         assert(cmd_ctx);
352
353         if (goi->argc < 3) {
354                 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
355                 return JIM_ERR;
356         }
357         /* COMMAND */
358         jim_getopt_obj(goi, &new_cmd);
359         /* does this command exist? */
360         cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
361         if (cmd) {
362                 cp = Jim_GetString(new_cmd, NULL);
363                 Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
364                 return JIM_ERR;
365         }
366
367         /* Create it */
368         dap = calloc(1, sizeof(struct arm_dap_object));
369         if (!dap)
370                 return JIM_ERR;
371
372         dap_instance_init(&dap->dap);
373
374         cp = Jim_GetString(new_cmd, NULL);
375         dap->name = strdup(cp);
376
377         e = dap_configure(goi, dap);
378         if (e != JIM_OK)
379                 goto err;
380
381         if (!dap->dap.tap) {
382                 Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1);
383                 e = JIM_ERR;
384                 goto err;
385         }
386
387         e = dap_check_config(&dap->dap);
388         if (e != ERROR_OK) {
389                 e = JIM_ERR;
390                 goto err;
391         }
392
393         struct command_registration dap_create_commands[] = {
394                 {
395                         .name = cp,
396                         .mode = COMMAND_ANY,
397                         .help = "dap instance command group",
398                         .usage = "",
399                         .chain = dap_instance_commands,
400                 },
401                 COMMAND_REGISTRATION_DONE
402         };
403
404         /* don't expose the instance commands when using hla */
405         if (transport_is_hla())
406                 dap_create_commands[0].chain = NULL;
407
408         e = register_commands_with_data(cmd_ctx, NULL, dap_create_commands, dap);
409         if (e != ERROR_OK) {
410                 e = JIM_ERR;
411                 goto err;
412         }
413
414         list_add_tail(&dap->lh, &all_dap);
415
416         return JIM_OK;
417
418 err:
419         free(dap->name);
420         free(dap);
421         return e;
422 }
423
424 static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
425 {
426         struct jim_getopt_info goi;
427         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
428         if (goi.argc < 2) {
429                 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
430                         "<name> [<dap_options> ...]");
431                 return JIM_ERR;
432         }
433         return dap_create(&goi);
434 }
435
436 static int jim_dap_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
437 {
438         struct arm_dap_object *obj;
439
440         if (argc != 1) {
441                 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
442                 return JIM_ERR;
443         }
444         Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
445         list_for_each_entry(obj, &all_dap, lh) {
446                 Jim_ListAppendElement(interp, Jim_GetResult(interp),
447                         Jim_NewStringObj(interp, obj->name, -1));
448         }
449         return JIM_OK;
450 }
451
452 COMMAND_HANDLER(handle_dap_init)
453 {
454         return dap_init_all();
455 }
456
457 COMMAND_HANDLER(handle_dap_info_command)
458 {
459         struct target *target = get_current_target(CMD_CTX);
460         struct arm *arm = target_to_arm(target);
461         struct adiv5_dap *dap = arm->dap;
462         uint64_t apsel;
463
464         if (!dap) {
465                 LOG_ERROR("DAP instance not available. Probably a HLA target...");
466                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
467         }
468
469         switch (CMD_ARGC) {
470                 case 0:
471                         apsel = dap->apsel;
472                         break;
473                 case 1:
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 MEM-AP of current target "
519                 "(default currently selected AP)",
520                 .usage = "[ap_num]",
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 }