arm_adi_v5: parse ROM tables behind SoC-600 APv1 adapter
[fw/openocd] / src / target / arm_cti.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_cti.h"
28 #include "target/target.h"
29 #include "helper/time_support.h"
30 #include "helper/list.h"
31 #include "helper/command.h"
32
33 struct arm_cti {
34         struct list_head lh;
35         char *name;
36         struct adiv5_mem_ap_spot spot;
37         struct adiv5_ap *ap;
38 };
39
40 static LIST_HEAD(all_cti);
41
42 const char *arm_cti_name(struct arm_cti *self)
43 {
44         return self->name;
45 }
46
47 struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
48 {
49         struct arm_cti *obj = NULL;
50         const char *name;
51         bool found = false;
52
53         name = Jim_GetString(o, NULL);
54
55         list_for_each_entry(obj, &all_cti, lh) {
56                 if (!strcmp(name, obj->name)) {
57                         found = true;
58                         break;
59                 }
60         }
61
62         if (found)
63                 return obj;
64         return NULL;
65 }
66
67 static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value)
68 {
69         struct adiv5_ap *ap = self->ap;
70         uint32_t tmp;
71
72         /* Read register */
73         int retval = mem_ap_read_atomic_u32(ap, self->spot.base + reg, &tmp);
74         if (retval != ERROR_OK)
75                 return retval;
76
77         /* clear bitfield */
78         tmp &= ~mask;
79         /* put new value */
80         tmp |= value & mask;
81
82         /* write new value */
83         return mem_ap_write_atomic_u32(ap, self->spot.base + reg, tmp);
84 }
85
86 int arm_cti_enable(struct arm_cti *self, bool enable)
87 {
88         uint32_t val = enable ? 1 : 0;
89
90         return mem_ap_write_atomic_u32(self->ap, self->spot.base + CTI_CTR, val);
91 }
92
93 int arm_cti_ack_events(struct arm_cti *self, uint32_t event)
94 {
95         struct adiv5_ap *ap = self->ap;
96         int retval;
97         uint32_t tmp;
98
99         retval = mem_ap_write_atomic_u32(ap, self->spot.base + CTI_INACK, event);
100         if (retval == ERROR_OK) {
101                 int64_t then = timeval_ms();
102                 for (;;) {
103                         retval = mem_ap_read_atomic_u32(ap, self->spot.base + CTI_TROUT_STATUS, &tmp);
104                         if (retval != ERROR_OK)
105                                 break;
106                         if ((tmp & event) == 0)
107                                 break;
108                         if (timeval_ms() > then + 1000) {
109                                 LOG_ERROR("timeout waiting for target");
110                                 retval = ERROR_TARGET_TIMEOUT;
111                                 break;
112                         }
113                 }
114         }
115
116         return retval;
117 }
118
119 int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel)
120 {
121         if (channel > 31)
122                 return ERROR_COMMAND_ARGUMENT_INVALID;
123
124         return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0);
125 }
126
127 int arm_cti_ungate_channel(struct arm_cti *self, uint32_t channel)
128 {
129         if (channel > 31)
130                 return ERROR_COMMAND_ARGUMENT_INVALID;
131
132         return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0xFFFFFFFF);
133 }
134
135 int arm_cti_write_reg(struct arm_cti *self, unsigned int reg, uint32_t value)
136 {
137         return mem_ap_write_atomic_u32(self->ap, self->spot.base + reg, value);
138 }
139
140 int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *p_value)
141 {
142         if (!p_value)
143                 return ERROR_COMMAND_ARGUMENT_INVALID;
144
145         return mem_ap_read_atomic_u32(self->ap, self->spot.base + reg, p_value);
146 }
147
148 int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel)
149 {
150         if (channel > 31)
151                 return ERROR_COMMAND_ARGUMENT_INVALID;
152
153         return arm_cti_write_reg(self, CTI_APPPULSE, CTI_CHNL(channel));
154 }
155
156 int arm_cti_set_channel(struct arm_cti *self, uint32_t channel)
157 {
158         if (channel > 31)
159                 return ERROR_COMMAND_ARGUMENT_INVALID;
160
161         return arm_cti_write_reg(self, CTI_APPSET, CTI_CHNL(channel));
162 }
163
164 int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel)
165 {
166         if (channel > 31)
167                 return ERROR_COMMAND_ARGUMENT_INVALID;
168
169         return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel));
170 }
171
172 static uint32_t cti_regs[28];
173
174 static const struct {
175         uint32_t offset;
176         const char *label;
177         uint32_t *p_val;
178 } cti_names[] = {
179         { CTI_CTR,              "CTR",          &cti_regs[0] },
180         { CTI_GATE,             "GATE",         &cti_regs[1] },
181         { CTI_INEN0,    "INEN0",        &cti_regs[2] },
182         { CTI_INEN1,    "INEN1",        &cti_regs[3] },
183         { CTI_INEN2,    "INEN2",        &cti_regs[4] },
184         { CTI_INEN3,    "INEN3",        &cti_regs[5] },
185         { CTI_INEN4,    "INEN4",        &cti_regs[6] },
186         { CTI_INEN5,    "INEN5",        &cti_regs[7] },
187         { CTI_INEN6,    "INEN6",        &cti_regs[8] },
188         { CTI_INEN7,    "INEN7",        &cti_regs[9] },
189         { CTI_INEN8,    "INEN8",        &cti_regs[10] },
190         { CTI_OUTEN0,   "OUTEN0",       &cti_regs[11] },
191         { CTI_OUTEN1,   "OUTEN1",       &cti_regs[12] },
192         { CTI_OUTEN2,   "OUTEN2",       &cti_regs[13] },
193         { CTI_OUTEN3,   "OUTEN3",       &cti_regs[14] },
194         { CTI_OUTEN4,   "OUTEN4",       &cti_regs[15] },
195         { CTI_OUTEN5,   "OUTEN5",       &cti_regs[16] },
196         { CTI_OUTEN6,   "OUTEN6",       &cti_regs[17] },
197         { CTI_OUTEN7,   "OUTEN7",       &cti_regs[18] },
198         { CTI_OUTEN8,   "OUTEN8",       &cti_regs[19] },
199         { CTI_TRIN_STATUS,      "TRIN", &cti_regs[20] },
200         { CTI_TROUT_STATUS,     "TROUT", &cti_regs[21] },
201         { CTI_CHIN_STATUS,      "CHIN", &cti_regs[22] },
202         { CTI_CHOU_STATUS,      "CHOUT", &cti_regs[23] },
203         { CTI_APPSET,   "APPSET",       &cti_regs[24] },
204         { CTI_APPCLEAR, "APPCLR",       &cti_regs[25] },
205         { CTI_APPPULSE, "APPPULSE",     &cti_regs[26] },
206         { CTI_INACK,    "INACK",        &cti_regs[27] },
207 };
208
209 static int cti_find_reg_offset(const char *name)
210 {
211         unsigned int i;
212
213         for (i = 0; i < ARRAY_SIZE(cti_names); i++) {
214                 if (!strcmp(name, cti_names[i].label))
215                         return cti_names[i].offset;
216         }
217
218         LOG_ERROR("unknown CTI register %s", name);
219         return -1;
220 }
221
222 int arm_cti_cleanup_all(void)
223 {
224         struct arm_cti *obj, *tmp;
225
226         list_for_each_entry_safe(obj, tmp, &all_cti, lh) {
227                 if (obj->ap)
228                         dap_put_ap(obj->ap);
229                 free(obj->name);
230                 free(obj);
231         }
232
233         return ERROR_OK;
234 }
235
236 COMMAND_HANDLER(handle_cti_dump)
237 {
238         struct arm_cti *cti = CMD_DATA;
239         struct adiv5_ap *ap = cti->ap;
240         int retval = ERROR_OK;
241
242         for (int i = 0; (retval == ERROR_OK) && (i < (int)ARRAY_SIZE(cti_names)); i++)
243                 retval = mem_ap_read_u32(ap,
244                                 cti->spot.base + cti_names[i].offset, cti_names[i].p_val);
245
246         if (retval == ERROR_OK)
247                 retval = dap_run(ap->dap);
248
249         if (retval != ERROR_OK)
250                 return JIM_ERR;
251
252         for (int i = 0; i < (int)ARRAY_SIZE(cti_names); i++)
253                 command_print(CMD, "%8.8s (0x%04"PRIx32") 0x%08"PRIx32,
254                                 cti_names[i].label, cti_names[i].offset, *cti_names[i].p_val);
255
256         return JIM_OK;
257 }
258
259 COMMAND_HANDLER(handle_cti_enable)
260 {
261         struct arm_cti *cti = CMD_DATA;
262         bool on_off;
263
264         if (CMD_ARGC != 1)
265                 return ERROR_COMMAND_SYNTAX_ERROR;
266
267         COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
268
269         return arm_cti_enable(cti, on_off);
270 }
271
272 COMMAND_HANDLER(handle_cti_testmode)
273 {
274         struct arm_cti *cti = CMD_DATA;
275         bool on_off;
276
277         if (CMD_ARGC != 1)
278                 return ERROR_COMMAND_SYNTAX_ERROR;
279
280         COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
281
282         return arm_cti_write_reg(cti, 0xf00, on_off ? 0x1 : 0x0);
283 }
284
285 COMMAND_HANDLER(handle_cti_write)
286 {
287         struct arm_cti *cti = CMD_DATA;
288         int offset;
289         uint32_t value;
290
291         if (CMD_ARGC != 2)
292                 return ERROR_COMMAND_SYNTAX_ERROR;
293
294         offset = cti_find_reg_offset(CMD_ARGV[0]);
295         if (offset < 0)
296                 return ERROR_FAIL;
297
298         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
299
300         return arm_cti_write_reg(cti, offset, value);
301 }
302
303 COMMAND_HANDLER(handle_cti_read)
304 {
305         struct arm_cti *cti = CMD_DATA;
306         int offset;
307         int retval;
308         uint32_t value;
309
310         if (CMD_ARGC != 1)
311                 return ERROR_COMMAND_SYNTAX_ERROR;
312
313         offset = cti_find_reg_offset(CMD_ARGV[0]);
314         if (offset < 0)
315                 return ERROR_FAIL;
316
317         retval = arm_cti_read_reg(cti, offset, &value);
318         if (retval != ERROR_OK)
319                 return retval;
320
321         command_print(CMD, "0x%08"PRIx32, value);
322
323         return ERROR_OK;
324 }
325
326 COMMAND_HANDLER(handle_cti_ack)
327 {
328         struct arm_cti *cti = CMD_DATA;
329         uint32_t event;
330
331         if (CMD_ARGC != 1)
332                 return ERROR_COMMAND_SYNTAX_ERROR;
333
334         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], event);
335
336         int retval = arm_cti_ack_events(cti, 1 << event);
337
338
339         if (retval != ERROR_OK)
340                 return retval;
341
342         return ERROR_OK;
343 }
344
345 COMMAND_HANDLER(handle_cti_channel)
346 {
347         struct arm_cti *cti = CMD_DATA;
348         int retval = ERROR_OK;
349         uint32_t ch_num;
350
351         if (CMD_ARGC != 2)
352                 return ERROR_COMMAND_SYNTAX_ERROR;
353
354         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], ch_num);
355
356         if (!strcmp(CMD_ARGV[1], "gate"))
357                 retval = arm_cti_gate_channel(cti, ch_num);
358         else if (!strcmp(CMD_ARGV[1], "ungate"))
359                 retval = arm_cti_ungate_channel(cti, ch_num);
360         else if (!strcmp(CMD_ARGV[1], "pulse"))
361                 retval = arm_cti_pulse_channel(cti, ch_num);
362         else if (!strcmp(CMD_ARGV[1], "set"))
363                 retval = arm_cti_set_channel(cti, ch_num);
364         else if (!strcmp(CMD_ARGV[1], "clear"))
365                 retval = arm_cti_clear_channel(cti, ch_num);
366         else {
367                 command_print(CMD, "Possible channel operations: gate|ungate|set|clear|pulse");
368                 return ERROR_COMMAND_ARGUMENT_INVALID;
369         }
370
371         if (retval != ERROR_OK)
372                 return retval;
373
374         return ERROR_OK;
375 }
376
377 static const struct command_registration cti_instance_command_handlers[] = {
378         {
379                 .name  = "dump",
380                 .mode  = COMMAND_EXEC,
381                 .handler = handle_cti_dump,
382                 .help  = "dump CTI registers",
383                 .usage = "",
384         },
385         {
386                 .name = "enable",
387                 .mode = COMMAND_EXEC,
388                 .handler = handle_cti_enable,
389                 .help = "enable or disable the CTI",
390                 .usage = "'on'|'off'",
391         },
392         {
393                 .name = "testmode",
394                 .mode = COMMAND_EXEC,
395                 .handler = handle_cti_testmode,
396                 .help = "enable or disable integration test mode",
397                 .usage = "'on'|'off'",
398         },
399         {
400                 .name = "write",
401                 .mode = COMMAND_EXEC,
402                 .handler = handle_cti_write,
403                 .help = "write to a CTI register",
404                 .usage = "register_name value",
405         },
406         {
407                 .name = "read",
408                 .mode = COMMAND_EXEC,
409                 .handler = handle_cti_read,
410                 .help = "read a CTI register",
411                 .usage = "register_name",
412         },
413         {
414                 .name = "ack",
415                 .mode = COMMAND_EXEC,
416                 .handler = handle_cti_ack,
417                 .help = "acknowledge a CTI event",
418                 .usage = "event",
419         },
420         {
421                 .name = "channel",
422                 .mode = COMMAND_EXEC,
423                 .handler = handle_cti_channel,
424                 .help = "do an operation on one CTI channel, possible operations: "
425                                 "gate, ungate, set, clear and pulse",
426                 .usage = "channel_number operation",
427         },
428         COMMAND_REGISTRATION_DONE
429 };
430
431 static int cti_configure(struct jim_getopt_info *goi, struct arm_cti *cti)
432 {
433         /* parse config or cget options ... */
434         while (goi->argc > 0) {
435                 int e = adiv5_jim_mem_ap_spot_configure(&cti->spot, goi);
436
437                 if (e == JIM_CONTINUE)
438                         Jim_SetResultFormatted(goi->interp, "unknown option '%s'",
439                                 Jim_String(goi->argv[0]));
440
441                 if (e != JIM_OK)
442                         return JIM_ERR;
443         }
444
445         if (!cti->spot.dap) {
446                 Jim_SetResultString(goi->interp, "-dap required when creating CTI", -1);
447                 return JIM_ERR;
448         }
449
450         return JIM_OK;
451 }
452 static int cti_create(struct jim_getopt_info *goi)
453 {
454         struct command_context *cmd_ctx;
455         static struct arm_cti *cti;
456         Jim_Obj *new_cmd;
457         Jim_Cmd *cmd;
458         const char *cp;
459         int e;
460
461         cmd_ctx = current_command_context(goi->interp);
462         assert(cmd_ctx);
463
464         if (goi->argc < 3) {
465                 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
466                 return JIM_ERR;
467         }
468         /* COMMAND */
469         jim_getopt_obj(goi, &new_cmd);
470         /* does this command exist? */
471         cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
472         if (cmd) {
473                 cp = Jim_GetString(new_cmd, NULL);
474                 Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
475                 return JIM_ERR;
476         }
477
478         /* Create it */
479         cti = calloc(1, sizeof(*cti));
480         if (!cti)
481                 return JIM_ERR;
482
483         adiv5_mem_ap_spot_init(&cti->spot);
484
485         /* Do the rest as "configure" options */
486         goi->isconfigure = 1;
487         e = cti_configure(goi, cti);
488         if (e != JIM_OK) {
489                 free(cti);
490                 return e;
491         }
492
493         cp = Jim_GetString(new_cmd, NULL);
494         cti->name = strdup(cp);
495
496         /* now - create the new cti name command */
497         const struct command_registration cti_subcommands[] = {
498                 {
499                         .chain = cti_instance_command_handlers,
500                 },
501                 COMMAND_REGISTRATION_DONE
502         };
503         const struct command_registration cti_commands[] = {
504                 {
505                         .name = cp,
506                         .mode = COMMAND_ANY,
507                         .help = "cti instance command group",
508                         .usage = "",
509                         .chain = cti_subcommands,
510                 },
511                 COMMAND_REGISTRATION_DONE
512         };
513         e = register_commands_with_data(cmd_ctx, NULL, cti_commands, cti);
514         if (e != ERROR_OK)
515                 return JIM_ERR;
516
517         list_add_tail(&cti->lh, &all_cti);
518
519         cti->ap = dap_get_ap(cti->spot.dap, cti->spot.ap_num);
520         if (!cti->ap) {
521                 Jim_SetResultString(goi->interp, "Cannot get AP", -1);
522                 return JIM_ERR;
523         }
524
525         return JIM_OK;
526 }
527
528 static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
529 {
530         struct jim_getopt_info goi;
531         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
532         if (goi.argc < 2) {
533                 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
534                         "<name> [<cti_options> ...]");
535                 return JIM_ERR;
536         }
537         return cti_create(&goi);
538 }
539
540 static int jim_cti_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
541 {
542         struct arm_cti *obj;
543
544         if (argc != 1) {
545                 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
546                 return JIM_ERR;
547         }
548         Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
549         list_for_each_entry(obj, &all_cti, lh) {
550                 Jim_ListAppendElement(interp, Jim_GetResult(interp),
551                         Jim_NewStringObj(interp, obj->name, -1));
552         }
553         return JIM_OK;
554 }
555
556
557 static const struct command_registration cti_subcommand_handlers[] = {
558         {
559                 .name = "create",
560                 .mode = COMMAND_ANY,
561                 .jim_handler = jim_cti_create,
562                 .usage = "name '-chain-position' name [options ...]",
563                 .help = "Creates a new CTI object",
564         },
565         {
566                 .name = "names",
567                 .mode = COMMAND_ANY,
568                 .jim_handler = jim_cti_names,
569                 .usage = "",
570                 .help = "Lists all registered CTI objects by name",
571         },
572         COMMAND_REGISTRATION_DONE
573 };
574
575 static const struct command_registration cti_command_handlers[] = {
576         {
577                 .name = "cti",
578                 .mode = COMMAND_CONFIG,
579                 .help = "CTI commands",
580                 .chain = cti_subcommand_handlers,
581                 .usage = "",
582         },
583         COMMAND_REGISTRATION_DONE
584 };
585
586 int cti_register_commands(struct command_context *cmd_ctx)
587 {
588         return register_commands(cmd_ctx, NULL, cti_command_handlers);
589 }