1 /***************************************************************************
2 * Copyright (C) 2016 by Matthias Welwarsky *
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. *
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. *
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., *
18 ***************************************************************************/
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"
36 struct adiv5_mem_ap_spot spot;
40 static LIST_HEAD(all_cti);
42 const char *arm_cti_name(struct arm_cti *self)
47 struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
49 struct arm_cti *obj = NULL;
53 name = Jim_GetString(o, NULL);
55 list_for_each_entry(obj, &all_cti, lh) {
56 if (!strcmp(name, obj->name)) {
67 static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value)
69 struct adiv5_ap *ap = self->ap;
73 int retval = mem_ap_read_atomic_u32(ap, self->spot.base + reg, &tmp);
74 if (retval != ERROR_OK)
83 return mem_ap_write_atomic_u32(ap, self->spot.base + reg, tmp);
86 int arm_cti_enable(struct arm_cti *self, bool enable)
88 uint32_t val = enable ? 1 : 0;
90 return mem_ap_write_atomic_u32(self->ap, self->spot.base + CTI_CTR, val);
93 int arm_cti_ack_events(struct arm_cti *self, uint32_t event)
95 struct adiv5_ap *ap = self->ap;
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();
103 retval = mem_ap_read_atomic_u32(ap, self->spot.base + CTI_TROUT_STATUS, &tmp);
104 if (retval != ERROR_OK)
106 if ((tmp & event) == 0)
108 if (timeval_ms() > then + 1000) {
109 LOG_ERROR("timeout waiting for target");
110 retval = ERROR_TARGET_TIMEOUT;
119 int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel)
122 return ERROR_COMMAND_ARGUMENT_INVALID;
124 return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0);
127 int arm_cti_ungate_channel(struct arm_cti *self, uint32_t channel)
130 return ERROR_COMMAND_ARGUMENT_INVALID;
132 return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0xFFFFFFFF);
135 int arm_cti_write_reg(struct arm_cti *self, unsigned int reg, uint32_t value)
137 return mem_ap_write_atomic_u32(self->ap, self->spot.base + reg, value);
140 int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *p_value)
143 return ERROR_COMMAND_ARGUMENT_INVALID;
145 return mem_ap_read_atomic_u32(self->ap, self->spot.base + reg, p_value);
148 int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel)
151 return ERROR_COMMAND_ARGUMENT_INVALID;
153 return arm_cti_write_reg(self, CTI_APPPULSE, CTI_CHNL(channel));
156 int arm_cti_set_channel(struct arm_cti *self, uint32_t channel)
159 return ERROR_COMMAND_ARGUMENT_INVALID;
161 return arm_cti_write_reg(self, CTI_APPSET, CTI_CHNL(channel));
164 int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel)
167 return ERROR_COMMAND_ARGUMENT_INVALID;
169 return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel));
172 static uint32_t cti_regs[28];
174 static const struct {
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] },
209 static int cti_find_reg_offset(const char *name)
213 for (i = 0; i < ARRAY_SIZE(cti_names); i++) {
214 if (!strcmp(name, cti_names[i].label))
215 return cti_names[i].offset;
218 LOG_ERROR("unknown CTI register %s", name);
222 int arm_cti_cleanup_all(void)
224 struct arm_cti *obj, *tmp;
226 list_for_each_entry_safe(obj, tmp, &all_cti, lh) {
236 COMMAND_HANDLER(handle_cti_dump)
238 struct arm_cti *cti = CMD_DATA;
239 struct adiv5_ap *ap = cti->ap;
240 int retval = ERROR_OK;
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);
246 if (retval == ERROR_OK)
247 retval = dap_run(ap->dap);
249 if (retval != ERROR_OK)
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);
259 COMMAND_HANDLER(handle_cti_enable)
261 struct arm_cti *cti = CMD_DATA;
265 return ERROR_COMMAND_SYNTAX_ERROR;
267 COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
269 return arm_cti_enable(cti, on_off);
272 COMMAND_HANDLER(handle_cti_testmode)
274 struct arm_cti *cti = CMD_DATA;
278 return ERROR_COMMAND_SYNTAX_ERROR;
280 COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
282 return arm_cti_write_reg(cti, 0xf00, on_off ? 0x1 : 0x0);
285 COMMAND_HANDLER(handle_cti_write)
287 struct arm_cti *cti = CMD_DATA;
292 return ERROR_COMMAND_SYNTAX_ERROR;
294 offset = cti_find_reg_offset(CMD_ARGV[0]);
298 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
300 return arm_cti_write_reg(cti, offset, value);
303 COMMAND_HANDLER(handle_cti_read)
305 struct arm_cti *cti = CMD_DATA;
311 return ERROR_COMMAND_SYNTAX_ERROR;
313 offset = cti_find_reg_offset(CMD_ARGV[0]);
317 retval = arm_cti_read_reg(cti, offset, &value);
318 if (retval != ERROR_OK)
321 command_print(CMD, "0x%08"PRIx32, value);
326 COMMAND_HANDLER(handle_cti_ack)
328 struct arm_cti *cti = CMD_DATA;
332 return ERROR_COMMAND_SYNTAX_ERROR;
334 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], event);
336 int retval = arm_cti_ack_events(cti, 1 << event);
339 if (retval != ERROR_OK)
345 COMMAND_HANDLER(handle_cti_channel)
347 struct arm_cti *cti = CMD_DATA;
348 int retval = ERROR_OK;
352 return ERROR_COMMAND_SYNTAX_ERROR;
354 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], ch_num);
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);
367 command_print(CMD, "Possible channel operations: gate|ungate|set|clear|pulse");
368 return ERROR_COMMAND_ARGUMENT_INVALID;
371 if (retval != ERROR_OK)
377 static const struct command_registration cti_instance_command_handlers[] = {
380 .mode = COMMAND_EXEC,
381 .handler = handle_cti_dump,
382 .help = "dump CTI registers",
387 .mode = COMMAND_EXEC,
388 .handler = handle_cti_enable,
389 .help = "enable or disable the CTI",
390 .usage = "'on'|'off'",
394 .mode = COMMAND_EXEC,
395 .handler = handle_cti_testmode,
396 .help = "enable or disable integration test mode",
397 .usage = "'on'|'off'",
401 .mode = COMMAND_EXEC,
402 .handler = handle_cti_write,
403 .help = "write to a CTI register",
404 .usage = "register_name value",
408 .mode = COMMAND_EXEC,
409 .handler = handle_cti_read,
410 .help = "read a CTI register",
411 .usage = "register_name",
415 .mode = COMMAND_EXEC,
416 .handler = handle_cti_ack,
417 .help = "acknowledge a CTI event",
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",
428 COMMAND_REGISTRATION_DONE
431 static int cti_configure(struct jim_getopt_info *goi, struct arm_cti *cti)
433 /* parse config or cget options ... */
434 while (goi->argc > 0) {
435 int e = adiv5_jim_mem_ap_spot_configure(&cti->spot, goi);
437 if (e == JIM_CONTINUE)
438 Jim_SetResultFormatted(goi->interp, "unknown option '%s'",
439 Jim_String(goi->argv[0]));
445 if (!cti->spot.dap) {
446 Jim_SetResultString(goi->interp, "-dap required when creating CTI", -1);
452 static int cti_create(struct jim_getopt_info *goi)
454 struct command_context *cmd_ctx;
455 static struct arm_cti *cti;
461 cmd_ctx = current_command_context(goi->interp);
465 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
469 jim_getopt_obj(goi, &new_cmd);
470 /* does this command exist? */
471 cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
473 cp = Jim_GetString(new_cmd, NULL);
474 Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
479 cti = calloc(1, sizeof(*cti));
483 adiv5_mem_ap_spot_init(&cti->spot);
485 /* Do the rest as "configure" options */
486 goi->isconfigure = 1;
487 e = cti_configure(goi, cti);
493 cp = Jim_GetString(new_cmd, NULL);
494 cti->name = strdup(cp);
496 /* now - create the new cti name command */
497 const struct command_registration cti_subcommands[] = {
499 .chain = cti_instance_command_handlers,
501 COMMAND_REGISTRATION_DONE
503 const struct command_registration cti_commands[] = {
507 .help = "cti instance command group",
509 .chain = cti_subcommands,
511 COMMAND_REGISTRATION_DONE
513 e = register_commands_with_data(cmd_ctx, NULL, cti_commands, cti);
517 list_add_tail(&cti->lh, &all_cti);
519 cti->ap = dap_get_ap(cti->spot.dap, cti->spot.ap_num);
521 Jim_SetResultString(goi->interp, "Cannot get AP", -1);
528 static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
530 struct jim_getopt_info goi;
531 jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
533 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
534 "<name> [<cti_options> ...]");
537 return cti_create(&goi);
540 static int jim_cti_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
545 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
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));
557 static const struct command_registration cti_subcommand_handlers[] = {
561 .jim_handler = jim_cti_create,
562 .usage = "name '-chain-position' name [options ...]",
563 .help = "Creates a new CTI object",
568 .jim_handler = jim_cti_names,
570 .help = "Lists all registered CTI objects by name",
572 COMMAND_REGISTRATION_DONE
575 static const struct command_registration cti_command_handlers[] = {
578 .mode = COMMAND_CONFIG,
579 .help = "CTI commands",
580 .chain = cti_subcommand_handlers,
583 COMMAND_REGISTRATION_DONE
586 int cti_register_commands(struct command_context *cmd_ctx)
588 return register_commands(cmd_ctx, NULL, cti_command_handlers);