openocd: use unique name for struct command_registration
[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 = i;
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         }
62         INIT_LIST_HEAD(&dap->cmd_journal);
63         INIT_LIST_HEAD(&dap->cmd_pool);
64 }
65
66 const char *adiv5_dap_name(struct adiv5_dap *self)
67 {
68         struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
69         return obj->name;
70 }
71
72 const struct swd_driver *adiv5_dap_swd_driver(struct adiv5_dap *self)
73 {
74         struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
75         return obj->swd;
76 }
77
78 struct adiv5_dap *adiv5_get_dap(struct arm_dap_object *obj)
79 {
80         return &obj->dap;
81 }
82 struct adiv5_dap *dap_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
83 {
84         struct arm_dap_object *obj = NULL;
85         const char *name;
86         bool found = false;
87
88         name = Jim_GetString(o, NULL);
89
90         list_for_each_entry(obj, &all_dap, lh) {
91                 if (!strcmp(name, obj->name)) {
92                         found = true;
93                         break;
94                 }
95         }
96
97         if (found)
98                 return &obj->dap;
99         return NULL;
100 }
101
102 static int dap_init_all(void)
103 {
104         struct arm_dap_object *obj;
105         int retval;
106
107         LOG_DEBUG("Initializing all DAPs ...");
108
109         list_for_each_entry(obj, &all_dap, lh) {
110                 struct adiv5_dap *dap = &obj->dap;
111
112                 /* with hla, dap is just a dummy */
113                 if (transport_is_hla())
114                         continue;
115
116                 /* skip taps that are disabled */
117                 if (!dap->tap->enabled)
118                         continue;
119
120                 if (transport_is_swd()) {
121                         dap->ops = &swd_dap_ops;
122                         obj->swd = adapter_driver->swd_ops;
123                 } else if (transport_is_dapdirect_swd()) {
124                         dap->ops = adapter_driver->dap_swd_ops;
125                 } else if (transport_is_dapdirect_jtag()) {
126                         dap->ops = adapter_driver->dap_jtag_ops;
127                 } else
128                         dap->ops = &jtag_dp_ops;
129
130                 retval = dap->ops->connect(dap);
131                 if (retval != ERROR_OK)
132                         return retval;
133         }
134
135         return ERROR_OK;
136 }
137
138 int dap_cleanup_all(void)
139 {
140         struct arm_dap_object *obj, *tmp;
141         struct adiv5_dap *dap;
142
143         list_for_each_entry_safe(obj, tmp, &all_dap, lh) {
144                 dap = &obj->dap;
145                 if (dap->ops && dap->ops->quit)
146                         dap->ops->quit(dap);
147
148                 free(obj->name);
149                 free(obj);
150         }
151
152         return ERROR_OK;
153 }
154
155 enum dap_cfg_param {
156         CFG_CHAIN_POSITION,
157         CFG_IGNORE_SYSPWRUPACK,
158         CFG_DP_ID,
159         CFG_INSTANCE_ID,
160 };
161
162 static const struct jim_nvp nvp_config_opts[] = {
163         { .name = "-chain-position",     .value = CFG_CHAIN_POSITION },
164         { .name = "-ignore-syspwrupack", .value = CFG_IGNORE_SYSPWRUPACK },
165         { .name = "-dp-id",              .value = CFG_DP_ID },
166         { .name = "-instance-id",        .value = CFG_INSTANCE_ID },
167         { .name = NULL, .value = -1 }
168 };
169
170 static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap)
171 {
172         struct jim_nvp *n;
173         int e;
174
175         /* parse config ... */
176         while (goi->argc > 0) {
177                 Jim_SetEmptyResult(goi->interp);
178
179                 e = jim_getopt_nvp(goi, nvp_config_opts, &n);
180                 if (e != JIM_OK) {
181                         jim_getopt_nvp_unknown(goi, nvp_config_opts, 0);
182                         return e;
183                 }
184                 switch (n->value) {
185                 case CFG_CHAIN_POSITION: {
186                         Jim_Obj *o_t;
187                         e = jim_getopt_obj(goi, &o_t);
188                         if (e != JIM_OK)
189                                 return e;
190
191                         struct jtag_tap *tap;
192                         tap = jtag_tap_by_jim_obj(goi->interp, o_t);
193                         if (!tap) {
194                                 Jim_SetResultString(goi->interp, "-chain-position is invalid", -1);
195                                 return JIM_ERR;
196                         }
197                         dap->dap.tap = tap;
198                         /* loop for more */
199                         break;
200                 }
201                 case CFG_IGNORE_SYSPWRUPACK:
202                         dap->dap.ignore_syspwrupack = true;
203                         break;
204                 case CFG_DP_ID: {
205                         jim_wide w;
206                         e = jim_getopt_wide(goi, &w);
207                         if (e != JIM_OK) {
208                                 Jim_SetResultFormatted(goi->interp,
209                                                 "create %s: bad parameter %s",
210                                                 dap->name, n->name);
211                                 return JIM_ERR;
212                         }
213                         if (w < 0 || w > DP_TARGETSEL_DPID_MASK) {
214                                 Jim_SetResultFormatted(goi->interp,
215                                                 "create %s: %s out of range",
216                                                 dap->name, n->name);
217                                 return JIM_ERR;
218                         }
219                         dap->dap.multidrop_targetsel =
220                                 (dap->dap.multidrop_targetsel & DP_TARGETSEL_INSTANCEID_MASK)
221                                 | (w & DP_TARGETSEL_DPID_MASK);
222                         dap->dap.multidrop_dp_id_valid = true;
223                         break;
224                 }
225                 case CFG_INSTANCE_ID: {
226                         jim_wide w;
227                         e = jim_getopt_wide(goi, &w);
228                         if (e != JIM_OK) {
229                                 Jim_SetResultFormatted(goi->interp,
230                                                 "create %s: bad parameter %s",
231                                                 dap->name, n->name);
232                                 return JIM_ERR;
233                         }
234                         if (w < 0 || w > 15) {
235                                 Jim_SetResultFormatted(goi->interp,
236                                                 "create %s: %s out of range",
237                                                 dap->name, n->name);
238                                 return JIM_ERR;
239                         }
240                         dap->dap.multidrop_targetsel =
241                                 (dap->dap.multidrop_targetsel & DP_TARGETSEL_DPID_MASK)
242                                 | ((w << DP_TARGETSEL_INSTANCEID_SHIFT) & DP_TARGETSEL_INSTANCEID_MASK);
243                         dap->dap.multidrop_instance_id_valid = true;
244                         break;
245                 }
246                 default:
247                         break;
248                 }
249         }
250
251         return JIM_OK;
252 }
253
254 static int dap_check_config(struct adiv5_dap *dap)
255 {
256         if (transport_is_jtag() || transport_is_dapdirect_jtag() || transport_is_hla())
257                 return ERROR_OK;
258
259         struct arm_dap_object *obj;
260         bool new_multidrop = dap_is_multidrop(dap);
261         bool had_multidrop = new_multidrop;
262         uint32_t targetsel = dap->multidrop_targetsel;
263         unsigned int non_multidrop_count = had_multidrop ? 0 : 1;
264
265         list_for_each_entry(obj, &all_dap, lh) {
266                 struct adiv5_dap *dap_it = &obj->dap;
267
268                 if (transport_is_swd()) {
269                         if (dap_is_multidrop(dap_it)) {
270                                 had_multidrop = true;
271                                 if (new_multidrop && dap_it->multidrop_targetsel == targetsel) {
272                                         uint32_t dp_id = targetsel & DP_TARGETSEL_DPID_MASK;
273                                         uint32_t instance_id = targetsel >> DP_TARGETSEL_INSTANCEID_SHIFT;
274                                         LOG_ERROR("%s and %s have the same multidrop selectors -dp-id 0x%08"
275                                                           PRIx32 " and -instance-id 0x%" PRIx32,
276                                                           obj->name, adiv5_dap_name(dap),
277                                                           dp_id, instance_id);
278                                         return ERROR_FAIL;
279                                 }
280                         } else {
281                                 non_multidrop_count++;
282                         }
283                 } else if (transport_is_dapdirect_swd()) {
284                         non_multidrop_count++;
285                 }
286         }
287
288         if (non_multidrop_count > 1) {
289                 LOG_ERROR("Two or more SWD non multidrop DAPs are not supported");
290                 return ERROR_FAIL;
291         }
292         if (had_multidrop && non_multidrop_count) {
293                 LOG_ERROR("Mixing of SWD multidrop DAPs and non multidrop DAPs is not supported");
294                 return ERROR_FAIL;
295         }
296
297         return ERROR_OK;
298 }
299
300 static int dap_create(struct jim_getopt_info *goi)
301 {
302         struct command_context *cmd_ctx;
303         static struct arm_dap_object *dap;
304         Jim_Obj *new_cmd;
305         Jim_Cmd *cmd;
306         const char *cp;
307         int e;
308
309         cmd_ctx = current_command_context(goi->interp);
310         assert(cmd_ctx);
311
312         if (goi->argc < 3) {
313                 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
314                 return JIM_ERR;
315         }
316         /* COMMAND */
317         jim_getopt_obj(goi, &new_cmd);
318         /* does this command exist? */
319         cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
320         if (cmd) {
321                 cp = Jim_GetString(new_cmd, NULL);
322                 Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
323                 return JIM_ERR;
324         }
325
326         /* Create it */
327         dap = calloc(1, sizeof(struct arm_dap_object));
328         if (!dap)
329                 return JIM_ERR;
330
331         dap_instance_init(&dap->dap);
332
333         cp = Jim_GetString(new_cmd, NULL);
334         dap->name = strdup(cp);
335
336         e = dap_configure(goi, dap);
337         if (e != JIM_OK)
338                 goto err;
339
340         if (!dap->dap.tap) {
341                 Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1);
342                 e = JIM_ERR;
343                 goto err;
344         }
345
346         e = dap_check_config(&dap->dap);
347         if (e != ERROR_OK) {
348                 e = JIM_ERR;
349                 goto err;
350         }
351
352         struct command_registration dap_create_commands[] = {
353                 {
354                         .name = cp,
355                         .mode = COMMAND_ANY,
356                         .help = "dap instance command group",
357                         .usage = "",
358                         .chain = dap_instance_commands,
359                 },
360                 COMMAND_REGISTRATION_DONE
361         };
362
363         /* don't expose the instance commands when using hla */
364         if (transport_is_hla())
365                 dap_create_commands[0].chain = NULL;
366
367         e = register_commands_with_data(cmd_ctx, NULL, dap_create_commands, dap);
368         if (e != ERROR_OK) {
369                 e = JIM_ERR;
370                 goto err;
371         }
372
373         list_add_tail(&dap->lh, &all_dap);
374
375         return JIM_OK;
376
377 err:
378         free(dap->name);
379         free(dap);
380         return e;
381 }
382
383 static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
384 {
385         struct jim_getopt_info goi;
386         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
387         if (goi.argc < 2) {
388                 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
389                         "<name> [<dap_options> ...]");
390                 return JIM_ERR;
391         }
392         return dap_create(&goi);
393 }
394
395 static int jim_dap_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
396 {
397         struct arm_dap_object *obj;
398
399         if (argc != 1) {
400                 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
401                 return JIM_ERR;
402         }
403         Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
404         list_for_each_entry(obj, &all_dap, lh) {
405                 Jim_ListAppendElement(interp, Jim_GetResult(interp),
406                         Jim_NewStringObj(interp, obj->name, -1));
407         }
408         return JIM_OK;
409 }
410
411 COMMAND_HANDLER(handle_dap_init)
412 {
413         return dap_init_all();
414 }
415
416 COMMAND_HANDLER(handle_dap_info_command)
417 {
418         struct target *target = get_current_target(CMD_CTX);
419         struct arm *arm = target_to_arm(target);
420         struct adiv5_dap *dap = arm->dap;
421         uint32_t apsel;
422
423         if (!dap) {
424                 LOG_ERROR("DAP instance not available. Probably a HLA target...");
425                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
426         }
427
428         switch (CMD_ARGC) {
429                 case 0:
430                         apsel = dap->apsel;
431                         break;
432                 case 1:
433                         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
434                         if (apsel > DP_APSEL_MAX)
435                                 return ERROR_COMMAND_SYNTAX_ERROR;
436                         break;
437                 default:
438                         return ERROR_COMMAND_SYNTAX_ERROR;
439         }
440
441         return dap_info_command(CMD, &dap->ap[apsel]);
442 }
443
444 static const struct command_registration dap_subcommand_handlers[] = {
445         {
446                 .name = "create",
447                 .mode = COMMAND_ANY,
448                 .jim_handler = jim_dap_create,
449                 .usage = "name '-chain-position' name",
450                 .help = "Creates a new DAP instance",
451         },
452         {
453                 .name = "names",
454                 .mode = COMMAND_ANY,
455                 .jim_handler = jim_dap_names,
456                 .usage = "",
457                 .help = "Lists all registered DAP instances by name",
458         },
459         {
460                 .name = "init",
461                 .mode = COMMAND_ANY,
462                 .handler = handle_dap_init,
463                 .usage = "",
464                 .help = "Initialize all registered DAP instances"
465         },
466         {
467                 .name = "info",
468                 .handler = handle_dap_info_command,
469                 .mode = COMMAND_EXEC,
470                 .help = "display ROM table for MEM-AP of current target "
471                 "(default currently selected AP)",
472                 .usage = "[ap_num]",
473         },
474         COMMAND_REGISTRATION_DONE
475 };
476
477 static const struct command_registration dap_commands[] = {
478         {
479                 .name = "dap",
480                 .mode = COMMAND_CONFIG,
481                 .help = "DAP commands",
482                 .chain = dap_subcommand_handlers,
483                 .usage = "",
484         },
485         COMMAND_REGISTRATION_DONE
486 };
487
488 int dap_register_commands(struct command_context *cmd_ctx)
489 {
490         return register_commands(cmd_ctx, NULL, dap_commands);
491 }