target/arm_adi_v5,arm_dap: introduce multidrop_targetsel and its configuration
[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_create(struct jim_getopt_info *goi)
255 {
256         struct command_context *cmd_ctx;
257         static struct arm_dap_object *dap;
258         Jim_Obj *new_cmd;
259         Jim_Cmd *cmd;
260         const char *cp;
261         int e;
262
263         cmd_ctx = current_command_context(goi->interp);
264         assert(cmd_ctx);
265
266         if (goi->argc < 3) {
267                 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
268                 return JIM_ERR;
269         }
270         /* COMMAND */
271         jim_getopt_obj(goi, &new_cmd);
272         /* does this command exist? */
273         cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
274         if (cmd) {
275                 cp = Jim_GetString(new_cmd, NULL);
276                 Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
277                 return JIM_ERR;
278         }
279
280         /* Create it */
281         dap = calloc(1, sizeof(struct arm_dap_object));
282         if (!dap)
283                 return JIM_ERR;
284
285         dap_instance_init(&dap->dap);
286
287         cp = Jim_GetString(new_cmd, NULL);
288         dap->name = strdup(cp);
289
290         e = dap_configure(goi, dap);
291         if (e != JIM_OK)
292                 goto err;
293
294         if (!dap->dap.tap) {
295                 Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1);
296                 e = JIM_ERR;
297                 goto err;
298         }
299
300         struct command_registration dap_commands[] = {
301                 {
302                         .name = cp,
303                         .mode = COMMAND_ANY,
304                         .help = "dap instance command group",
305                         .usage = "",
306                         .chain = dap_instance_commands,
307                 },
308                 COMMAND_REGISTRATION_DONE
309         };
310
311         /* don't expose the instance commands when using hla */
312         if (transport_is_hla())
313                 dap_commands[0].chain = NULL;
314
315         e = register_commands_with_data(cmd_ctx, NULL, dap_commands, dap);
316         if (e != ERROR_OK) {
317                 e = JIM_ERR;
318                 goto err;
319         }
320
321         list_add_tail(&dap->lh, &all_dap);
322
323         return JIM_OK;
324
325 err:
326         free(dap->name);
327         free(dap);
328         return e;
329 }
330
331 static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
332 {
333         struct jim_getopt_info goi;
334         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
335         if (goi.argc < 2) {
336                 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
337                         "<name> [<dap_options> ...]");
338                 return JIM_ERR;
339         }
340         return dap_create(&goi);
341 }
342
343 static int jim_dap_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
344 {
345         struct arm_dap_object *obj;
346
347         if (argc != 1) {
348                 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
349                 return JIM_ERR;
350         }
351         Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
352         list_for_each_entry(obj, &all_dap, lh) {
353                 Jim_ListAppendElement(interp, Jim_GetResult(interp),
354                         Jim_NewStringObj(interp, obj->name, -1));
355         }
356         return JIM_OK;
357 }
358
359 COMMAND_HANDLER(handle_dap_init)
360 {
361         return dap_init_all();
362 }
363
364 COMMAND_HANDLER(handle_dap_info_command)
365 {
366         struct target *target = get_current_target(CMD_CTX);
367         struct arm *arm = target_to_arm(target);
368         struct adiv5_dap *dap = arm->dap;
369         uint32_t apsel;
370
371         if (!dap) {
372                 LOG_ERROR("DAP instance not available. Probably a HLA target...");
373                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
374         }
375
376         switch (CMD_ARGC) {
377                 case 0:
378                         apsel = dap->apsel;
379                         break;
380                 case 1:
381                         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
382                         if (apsel > DP_APSEL_MAX)
383                                 return ERROR_COMMAND_SYNTAX_ERROR;
384                         break;
385                 default:
386                         return ERROR_COMMAND_SYNTAX_ERROR;
387         }
388
389         return dap_info_command(CMD, &dap->ap[apsel]);
390 }
391
392 static const struct command_registration dap_subcommand_handlers[] = {
393         {
394                 .name = "create",
395                 .mode = COMMAND_ANY,
396                 .jim_handler = jim_dap_create,
397                 .usage = "name '-chain-position' name",
398                 .help = "Creates a new DAP instance",
399         },
400         {
401                 .name = "names",
402                 .mode = COMMAND_ANY,
403                 .jim_handler = jim_dap_names,
404                 .usage = "",
405                 .help = "Lists all registered DAP instances by name",
406         },
407         {
408                 .name = "init",
409                 .mode = COMMAND_ANY,
410                 .handler = handle_dap_init,
411                 .usage = "",
412                 .help = "Initialize all registered DAP instances"
413         },
414         {
415                 .name = "info",
416                 .handler = handle_dap_info_command,
417                 .mode = COMMAND_EXEC,
418                 .help = "display ROM table for MEM-AP of current target "
419                 "(default currently selected AP)",
420                 .usage = "[ap_num]",
421         },
422         COMMAND_REGISTRATION_DONE
423 };
424
425 static const struct command_registration dap_commands[] = {
426         {
427                 .name = "dap",
428                 .mode = COMMAND_CONFIG,
429                 .help = "DAP commands",
430                 .chain = dap_subcommand_handlers,
431                 .usage = "",
432         },
433         COMMAND_REGISTRATION_DONE
434 };
435
436 int dap_register_commands(struct command_context *cmd_ctx)
437 {
438         return register_commands(cmd_ctx, NULL, dap_commands);
439 }