flash/nor/stm32l4x: Remove redundant error messages
[openocd.git] / src / target / arm_cti.c
blob7637ad01581f1c279744c5b38093f97afddede44
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2016 by Matthias Welwarsky *
5 * *
6 ***************************************************************************/
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
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"
21 struct arm_cti {
22 struct list_head lh;
23 char *name;
24 struct adiv5_mem_ap_spot spot;
25 struct adiv5_ap *ap;
28 static LIST_HEAD(all_cti);
30 const char *arm_cti_name(struct arm_cti *self)
32 return self->name;
35 struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
37 struct arm_cti *obj = NULL;
38 const char *name;
39 bool found = false;
41 name = Jim_GetString(o, NULL);
43 list_for_each_entry(obj, &all_cti, lh) {
44 if (!strcmp(name, obj->name)) {
45 found = true;
46 break;
50 if (found)
51 return obj;
52 return NULL;
55 static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value)
57 struct adiv5_ap *ap = self->ap;
58 uint32_t tmp;
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;
65 /* clear bitfield */
66 tmp &= ~mask;
67 /* put new value */
68 tmp |= value & mask;
70 /* write new value */
71 return mem_ap_write_atomic_u32(ap, self->spot.base + reg, tmp);
74 int arm_cti_enable(struct arm_cti *self, bool enable)
76 uint32_t val = enable ? 1 : 0;
78 return mem_ap_write_atomic_u32(self->ap, self->spot.base + CTI_CTR, val);
81 int arm_cti_ack_events(struct arm_cti *self, uint32_t event)
83 struct adiv5_ap *ap = self->ap;
84 int retval;
85 uint32_t tmp;
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;
104 return retval;
107 int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel)
109 if (channel > 31)
110 return ERROR_COMMAND_ARGUMENT_INVALID;
112 return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0);
115 int arm_cti_ungate_channel(struct arm_cti *self, uint32_t channel)
117 if (channel > 31)
118 return ERROR_COMMAND_ARGUMENT_INVALID;
120 return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0xFFFFFFFF);
123 int arm_cti_write_reg(struct arm_cti *self, unsigned int reg, uint32_t value)
125 return mem_ap_write_atomic_u32(self->ap, self->spot.base + reg, value);
128 int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *p_value)
130 if (!p_value)
131 return ERROR_COMMAND_ARGUMENT_INVALID;
133 return mem_ap_read_atomic_u32(self->ap, self->spot.base + reg, p_value);
136 int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel)
138 if (channel > 31)
139 return ERROR_COMMAND_ARGUMENT_INVALID;
141 return arm_cti_write_reg(self, CTI_APPPULSE, CTI_CHNL(channel));
144 int arm_cti_set_channel(struct arm_cti *self, uint32_t channel)
146 if (channel > 31)
147 return ERROR_COMMAND_ARGUMENT_INVALID;
149 return arm_cti_write_reg(self, CTI_APPSET, CTI_CHNL(channel));
152 int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel)
154 if (channel > 31)
155 return ERROR_COMMAND_ARGUMENT_INVALID;
157 return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel));
160 static uint32_t cti_regs[28];
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] },
197 static int cti_find_reg_offset(const char *name)
199 unsigned int i;
201 for (i = 0; i < ARRAY_SIZE(cti_names); i++) {
202 if (!strcmp(name, cti_names[i].label))
203 return cti_names[i].offset;
206 LOG_ERROR("unknown CTI register %s", name);
207 return -1;
210 int arm_cti_cleanup_all(void)
212 struct arm_cti *obj, *tmp;
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);
221 return ERROR_OK;
224 COMMAND_HANDLER(handle_cti_dump)
226 struct arm_cti *cti = CMD_DATA;
227 struct adiv5_ap *ap = cti->ap;
228 int retval = ERROR_OK;
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);
234 if (retval == ERROR_OK)
235 retval = dap_run(ap->dap);
237 if (retval != ERROR_OK)
238 return JIM_ERR;
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);
244 return JIM_OK;
247 COMMAND_HANDLER(handle_cti_enable)
249 struct arm_cti *cti = CMD_DATA;
250 bool on_off;
252 if (CMD_ARGC != 1)
253 return ERROR_COMMAND_SYNTAX_ERROR;
255 COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
257 return arm_cti_enable(cti, on_off);
260 COMMAND_HANDLER(handle_cti_testmode)
262 struct arm_cti *cti = CMD_DATA;
263 bool on_off;
265 if (CMD_ARGC != 1)
266 return ERROR_COMMAND_SYNTAX_ERROR;
268 COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
270 return arm_cti_write_reg(cti, 0xf00, on_off ? 0x1 : 0x0);
273 COMMAND_HANDLER(handle_cti_write)
275 struct arm_cti *cti = CMD_DATA;
276 int offset;
277 uint32_t value;
279 if (CMD_ARGC != 2)
280 return ERROR_COMMAND_SYNTAX_ERROR;
282 offset = cti_find_reg_offset(CMD_ARGV[0]);
283 if (offset < 0)
284 return ERROR_FAIL;
286 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
288 return arm_cti_write_reg(cti, offset, value);
291 COMMAND_HANDLER(handle_cti_read)
293 struct arm_cti *cti = CMD_DATA;
294 int offset;
295 int retval;
296 uint32_t value;
298 if (CMD_ARGC != 1)
299 return ERROR_COMMAND_SYNTAX_ERROR;
301 offset = cti_find_reg_offset(CMD_ARGV[0]);
302 if (offset < 0)
303 return ERROR_FAIL;
305 retval = arm_cti_read_reg(cti, offset, &value);
306 if (retval != ERROR_OK)
307 return retval;
309 command_print(CMD, "0x%08"PRIx32, value);
311 return ERROR_OK;
314 COMMAND_HANDLER(handle_cti_ack)
316 struct arm_cti *cti = CMD_DATA;
317 uint32_t event;
319 if (CMD_ARGC != 1)
320 return ERROR_COMMAND_SYNTAX_ERROR;
322 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], event);
324 int retval = arm_cti_ack_events(cti, 1 << event);
327 if (retval != ERROR_OK)
328 return retval;
330 return ERROR_OK;
333 COMMAND_HANDLER(handle_cti_channel)
335 struct arm_cti *cti = CMD_DATA;
336 int retval = ERROR_OK;
337 uint32_t ch_num;
339 if (CMD_ARGC != 2)
340 return ERROR_COMMAND_SYNTAX_ERROR;
342 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], ch_num);
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;
359 if (retval != ERROR_OK)
360 return retval;
362 return ERROR_OK;
365 static const struct command_registration cti_instance_command_handlers[] = {
367 .name = "dump",
368 .mode = COMMAND_EXEC,
369 .handler = handle_cti_dump,
370 .help = "dump CTI registers",
371 .usage = "",
374 .name = "enable",
375 .mode = COMMAND_EXEC,
376 .handler = handle_cti_enable,
377 .help = "enable or disable the CTI",
378 .usage = "'on'|'off'",
381 .name = "testmode",
382 .mode = COMMAND_EXEC,
383 .handler = handle_cti_testmode,
384 .help = "enable or disable integration test mode",
385 .usage = "'on'|'off'",
388 .name = "write",
389 .mode = COMMAND_EXEC,
390 .handler = handle_cti_write,
391 .help = "write to a CTI register",
392 .usage = "register_name value",
395 .name = "read",
396 .mode = COMMAND_EXEC,
397 .handler = handle_cti_read,
398 .help = "read a CTI register",
399 .usage = "register_name",
402 .name = "ack",
403 .mode = COMMAND_EXEC,
404 .handler = handle_cti_ack,
405 .help = "acknowledge a CTI event",
406 .usage = "event",
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",
416 COMMAND_REGISTRATION_DONE
419 static int cti_configure(struct jim_getopt_info *goi, struct arm_cti *cti)
421 /* parse config or cget options ... */
422 while (goi->argc > 0) {
423 int e = adiv5_jim_mem_ap_spot_configure(&cti->spot, goi);
425 if (e == JIM_CONTINUE)
426 Jim_SetResultFormatted(goi->interp, "unknown option '%s'",
427 Jim_String(goi->argv[0]));
429 if (e != JIM_OK)
430 return JIM_ERR;
433 if (!cti->spot.dap) {
434 Jim_SetResultString(goi->interp, "-dap required when creating CTI", -1);
435 return JIM_ERR;
438 return JIM_OK;
440 static int cti_create(struct jim_getopt_info *goi)
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;
449 cmd_ctx = current_command_context(goi->interp);
450 assert(cmd_ctx);
452 if (goi->argc < 3) {
453 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
454 return JIM_ERR;
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;
466 /* Create it */
467 cti = calloc(1, sizeof(*cti));
468 if (!cti)
469 return JIM_ERR;
471 adiv5_mem_ap_spot_init(&cti->spot);
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;
481 cp = Jim_GetString(new_cmd, NULL);
482 cti->name = strdup(cp);
484 /* now - create the new cti name command */
485 const struct command_registration cti_subcommands[] = {
487 .chain = cti_instance_command_handlers,
489 COMMAND_REGISTRATION_DONE
491 const struct command_registration cti_commands[] = {
493 .name = cp,
494 .mode = COMMAND_ANY,
495 .help = "cti instance command group",
496 .usage = "",
497 .chain = cti_subcommands,
499 COMMAND_REGISTRATION_DONE
501 e = register_commands_with_data(cmd_ctx, NULL, cti_commands, cti);
502 if (e != ERROR_OK)
503 return JIM_ERR;
505 list_add_tail(&cti->lh, &all_cti);
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;
513 return JIM_OK;
516 static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
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;
525 return cti_create(&goi);
528 COMMAND_HANDLER(cti_handle_names)
530 struct arm_cti *obj;
532 if (CMD_ARGC != 0)
533 return ERROR_COMMAND_SYNTAX_ERROR;
535 list_for_each_entry(obj, &all_cti, lh)
536 command_print(CMD, "%s", obj->name);
538 return ERROR_OK;
542 static const struct command_registration cti_subcommand_handlers[] = {
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",
551 .name = "names",
552 .mode = COMMAND_ANY,
553 .handler = cti_handle_names,
554 .usage = "",
555 .help = "Lists all registered CTI objects by name",
557 COMMAND_REGISTRATION_DONE
560 static const struct command_registration cti_command_handlers[] = {
562 .name = "cti",
563 .mode = COMMAND_CONFIG,
564 .help = "CTI commands",
565 .chain = cti_subcommand_handlers,
566 .usage = "",
568 COMMAND_REGISTRATION_DONE
571 int cti_register_commands(struct command_context *cmd_ctx)
573 return register_commands(cmd_ctx, NULL, cti_command_handlers);