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

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)