target/arm_dap: clean up dap_configure code
[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 };
159
160 static const struct jim_nvp nvp_config_opts[] = {
161         { .name = "-chain-position",   .value = CFG_CHAIN_POSITION },
162         { .name = "-ignore-syspwrupack", .value = CFG_IGNORE_SYSPWRUPACK },
163         { .name = NULL, .value = -1 }
164 };
165
166 static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap)
167 {
168         struct jim_nvp *n;
169         int e;
170
171         /* parse config ... */
172         while (goi->argc > 0) {
173                 Jim_SetEmptyResult(goi->interp);
174
175                 e = jim_getopt_nvp(goi, nvp_config_opts, &n);
176                 if (e != JIM_OK) {
177                         jim_getopt_nvp_unknown(goi, nvp_config_opts, 0);
178                         return e;
179                 }
180                 switch (n->value) {
181                 case CFG_CHAIN_POSITION: {
182                         Jim_Obj *o_t;
183                         e = jim_getopt_obj(goi, &o_t);
184                         if (e != JIM_OK)
185                                 return e;
186
187                         struct jtag_tap *tap;
188                         tap = jtag_tap_by_jim_obj(goi->interp, o_t);
189                         if (!tap) {
190                                 Jim_SetResultString(goi->interp, "-chain-position is invalid", -1);
191                                 return JIM_ERR;
192                         }
193                         dap->dap.tap = tap;
194                         /* loop for more */
195                         break;
196                 }
197                 case CFG_IGNORE_SYSPWRUPACK:
198                         dap->dap.ignore_syspwrupack = true;
199                         break;
200                 default:
201                         break;
202                 }
203         }
204
205         return JIM_OK;
206 }
207
208 static int dap_create(struct jim_getopt_info *goi)
209 {
210         struct command_context *cmd_ctx;
211         static struct arm_dap_object *dap;
212         Jim_Obj *new_cmd;
213         Jim_Cmd *cmd;
214         const char *cp;
215         int e;
216
217         cmd_ctx = current_command_context(goi->interp);
218         assert(cmd_ctx);
219
220         if (goi->argc < 3) {
221                 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
222                 return JIM_ERR;
223         }
224         /* COMMAND */
225         jim_getopt_obj(goi, &new_cmd);
226         /* does this command exist? */
227         cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
228         if (cmd) {
229                 cp = Jim_GetString(new_cmd, NULL);
230                 Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
231                 return JIM_ERR;
232         }
233
234         /* Create it */
235         dap = calloc(1, sizeof(struct arm_dap_object));
236         if (!dap)
237                 return JIM_ERR;
238
239         dap_instance_init(&dap->dap);
240
241         cp = Jim_GetString(new_cmd, NULL);
242         dap->name = strdup(cp);
243
244         e = dap_configure(goi, dap);
245         if (e != JIM_OK)
246                 goto err;
247
248         if (!dap->dap.tap) {
249                 Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1);
250                 e = JIM_ERR;
251                 goto err;
252         }
253
254         struct command_registration dap_commands[] = {
255                 {
256                         .name = cp,
257                         .mode = COMMAND_ANY,
258                         .help = "dap instance command group",
259                         .usage = "",
260                         .chain = dap_instance_commands,
261                 },
262                 COMMAND_REGISTRATION_DONE
263         };
264
265         /* don't expose the instance commands when using hla */
266         if (transport_is_hla())
267                 dap_commands[0].chain = NULL;
268
269         e = register_commands_with_data(cmd_ctx, NULL, dap_commands, dap);
270         if (e != ERROR_OK) {
271                 e = JIM_ERR;
272                 goto err;
273         }
274
275         list_add_tail(&dap->lh, &all_dap);
276
277         return JIM_OK;
278
279 err:
280         free(dap->name);
281         free(dap);
282         return e;
283 }
284
285 static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
286 {
287         struct jim_getopt_info goi;
288         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
289         if (goi.argc < 2) {
290                 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
291                         "<name> [<dap_options> ...]");
292                 return JIM_ERR;
293         }
294         return dap_create(&goi);
295 }
296
297 static int jim_dap_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
298 {
299         struct arm_dap_object *obj;
300
301         if (argc != 1) {
302                 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
303                 return JIM_ERR;
304         }
305         Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
306         list_for_each_entry(obj, &all_dap, lh) {
307                 Jim_ListAppendElement(interp, Jim_GetResult(interp),
308                         Jim_NewStringObj(interp, obj->name, -1));
309         }
310         return JIM_OK;
311 }
312
313 COMMAND_HANDLER(handle_dap_init)
314 {
315         return dap_init_all();
316 }
317
318 COMMAND_HANDLER(handle_dap_info_command)
319 {
320         struct target *target = get_current_target(CMD_CTX);
321         struct arm *arm = target_to_arm(target);
322         struct adiv5_dap *dap = arm->dap;
323         uint32_t apsel;
324
325         if (!dap) {
326                 LOG_ERROR("DAP instance not available. Probably a HLA target...");
327                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
328         }
329
330         switch (CMD_ARGC) {
331                 case 0:
332                         apsel = dap->apsel;
333                         break;
334                 case 1:
335                         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
336                         if (apsel > DP_APSEL_MAX)
337                                 return ERROR_COMMAND_SYNTAX_ERROR;
338                         break;
339                 default:
340                         return ERROR_COMMAND_SYNTAX_ERROR;
341         }
342
343         return dap_info_command(CMD, &dap->ap[apsel]);
344 }
345
346 static const struct command_registration dap_subcommand_handlers[] = {
347         {
348                 .name = "create",
349                 .mode = COMMAND_ANY,
350                 .jim_handler = jim_dap_create,
351                 .usage = "name '-chain-position' name",
352                 .help = "Creates a new DAP instance",
353         },
354         {
355                 .name = "names",
356                 .mode = COMMAND_ANY,
357                 .jim_handler = jim_dap_names,
358                 .usage = "",
359                 .help = "Lists all registered DAP instances by name",
360         },
361         {
362                 .name = "init",
363                 .mode = COMMAND_ANY,
364                 .handler = handle_dap_init,
365                 .usage = "",
366                 .help = "Initialize all registered DAP instances"
367         },
368         {
369                 .name = "info",
370                 .handler = handle_dap_info_command,
371                 .mode = COMMAND_EXEC,
372                 .help = "display ROM table for MEM-AP of current target "
373                 "(default currently selected AP)",
374                 .usage = "[ap_num]",
375         },
376         COMMAND_REGISTRATION_DONE
377 };
378
379 static const struct command_registration dap_commands[] = {
380         {
381                 .name = "dap",
382                 .mode = COMMAND_CONFIG,
383                 .help = "DAP commands",
384                 .chain = dap_subcommand_handlers,
385                 .usage = "",
386         },
387         COMMAND_REGISTRATION_DONE
388 };
389
390 int dap_register_commands(struct command_context *cmd_ctx)
391 {
392         return register_commands(cmd_ctx, NULL, dap_commands);
393 }