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"
38 struct arm_cti_object {
45 static LIST_HEAD(all_cti);
47 const char *arm_cti_name(struct arm_cti *self)
49 struct arm_cti_object *obj = container_of(self, struct arm_cti_object, cti);
53 struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
55 struct arm_cti_object *obj = NULL;
59 name = Jim_GetString(o, NULL);
61 list_for_each_entry(obj, &all_cti, lh) {
62 if (!strcmp(name, obj->name)) {
73 static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value)
78 int retval = mem_ap_read_atomic_u32(self->ap, self->base + reg, &tmp);
79 if (ERROR_OK != retval)
88 return mem_ap_write_atomic_u32(self->ap, self->base + reg, tmp);
91 int arm_cti_enable(struct arm_cti *self, bool enable)
93 uint32_t val = enable ? 1 : 0;
95 return mem_ap_write_atomic_u32(self->ap, self->base + CTI_CTR, val);
98 int arm_cti_ack_events(struct arm_cti *self, uint32_t event)
103 retval = mem_ap_write_atomic_u32(self->ap, self->base + CTI_INACK, event);
104 if (retval == ERROR_OK) {
105 int64_t then = timeval_ms();
107 retval = mem_ap_read_atomic_u32(self->ap, self->base + CTI_TROUT_STATUS, &tmp);
108 if (retval != ERROR_OK)
110 if ((tmp & event) == 0)
112 if (timeval_ms() > then + 1000) {
113 LOG_ERROR("timeout waiting for target");
114 retval = ERROR_TARGET_TIMEOUT;
123 int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel)
126 return ERROR_COMMAND_ARGUMENT_INVALID;
128 return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0);
131 int arm_cti_ungate_channel(struct arm_cti *self, uint32_t channel)
134 return ERROR_COMMAND_ARGUMENT_INVALID;
136 return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0xFFFFFFFF);
139 int arm_cti_write_reg(struct arm_cti *self, unsigned int reg, uint32_t value)
141 return mem_ap_write_atomic_u32(self->ap, self->base + reg, value);
144 int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *p_value)
147 return ERROR_COMMAND_ARGUMENT_INVALID;
149 return mem_ap_read_atomic_u32(self->ap, self->base + reg, p_value);
152 int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel)
155 return ERROR_COMMAND_ARGUMENT_INVALID;
157 return arm_cti_write_reg(self, CTI_APPPULSE, CTI_CHNL(channel));
160 int arm_cti_set_channel(struct arm_cti *self, uint32_t channel)
163 return ERROR_COMMAND_ARGUMENT_INVALID;
165 return arm_cti_write_reg(self, CTI_APPSET, CTI_CHNL(channel));
168 int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel)
171 return ERROR_COMMAND_ARGUMENT_INVALID;
173 return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel));
176 static uint32_t cti_regs[26];
178 static const struct {
183 { CTI_CTR, "CTR", &cti_regs[0] },
184 { CTI_GATE, "GATE", &cti_regs[1] },
185 { CTI_INEN0, "INEN0", &cti_regs[2] },
186 { CTI_INEN1, "INEN1", &cti_regs[3] },
187 { CTI_INEN2, "INEN2", &cti_regs[4] },
188 { CTI_INEN3, "INEN3", &cti_regs[5] },
189 { CTI_INEN4, "INEN4", &cti_regs[6] },
190 { CTI_INEN5, "INEN5", &cti_regs[7] },
191 { CTI_INEN6, "INEN6", &cti_regs[8] },
192 { CTI_INEN7, "INEN7", &cti_regs[9] },
193 { CTI_INEN8, "INEN8", &cti_regs[10] },
194 { CTI_OUTEN0, "OUTEN0", &cti_regs[11] },
195 { CTI_OUTEN1, "OUTEN1", &cti_regs[12] },
196 { CTI_OUTEN2, "OUTEN2", &cti_regs[13] },
197 { CTI_OUTEN3, "OUTEN3", &cti_regs[14] },
198 { CTI_OUTEN4, "OUTEN4", &cti_regs[15] },
199 { CTI_OUTEN5, "OUTEN5", &cti_regs[16] },
200 { CTI_OUTEN6, "OUTEN6", &cti_regs[17] },
201 { CTI_OUTEN7, "OUTEN7", &cti_regs[18] },
202 { CTI_OUTEN8, "OUTEN8", &cti_regs[19] },
203 { CTI_TRIN_STATUS, "TRIN", &cti_regs[20] },
204 { CTI_TROUT_STATUS, "TROUT", &cti_regs[21] },
205 { CTI_CHIN_STATUS, "CHIN", &cti_regs[22] },
206 { CTI_CHOU_STATUS, "CHOUT", &cti_regs[23] },
207 { CTI_APPSET, "APPSET", &cti_regs[24] },
208 { CTI_APPCLEAR, "APPCLR", &cti_regs[25] },
211 static int cti_find_reg_offset(const char *name)
215 for (i = 0; i < ARRAY_SIZE(cti_names); i++) {
216 if (!strcmp(name, cti_names[i].label))
217 return cti_names[i].offset;
222 COMMAND_HANDLER(handle_cti_dump)
224 struct arm_cti_object *obj = CMD_DATA;
225 struct arm_cti *cti = &obj->cti;
226 int retval = ERROR_OK;
228 for (int i = 0; (retval == ERROR_OK) && (i < (int)ARRAY_SIZE(cti_names)); i++)
229 retval = mem_ap_read_u32(cti->ap,
230 cti->base + cti_names[i].offset, cti_names[i].p_val);
232 if (retval == ERROR_OK)
233 retval = dap_run(cti->ap->dap);
235 if (retval != ERROR_OK)
238 for (int i = 0; i < (int)ARRAY_SIZE(cti_names); i++)
239 command_print(CMD_CTX, "%8.8s (0x%04"PRIx32") 0x%08"PRIx32,
240 cti_names[i].label, cti_names[i].offset, *cti_names[i].p_val);
245 COMMAND_HANDLER(handle_cti_enable)
247 struct arm_cti_object *obj = CMD_DATA;
248 Jim_Interp *interp = CMD_CTX->interp;
249 struct arm_cti *cti = &obj->cti;
253 Jim_SetResultString(interp, "wrong number of args", -1);
257 COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
259 return arm_cti_enable(cti, on_off);
262 COMMAND_HANDLER(handle_cti_testmode)
264 struct arm_cti_object *obj = CMD_DATA;
265 Jim_Interp *interp = CMD_CTX->interp;
266 struct arm_cti *cti = &obj->cti;
270 Jim_SetResultString(interp, "wrong number of args", -1);
274 COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
276 return arm_cti_write_reg(cti, 0xf00, on_off ? 0x1 : 0x0);
279 COMMAND_HANDLER(handle_cti_write)
281 struct arm_cti_object *obj = CMD_DATA;
282 Jim_Interp *interp = CMD_CTX->interp;
283 struct arm_cti *cti = &obj->cti;
288 Jim_SetResultString(interp, "Wrong numer of args", -1);
292 offset = cti_find_reg_offset(CMD_ARGV[0]);
296 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
298 return arm_cti_write_reg(cti, offset, value);
301 COMMAND_HANDLER(handle_cti_read)
303 struct arm_cti_object *obj = CMD_DATA;
304 Jim_Interp *interp = CMD_CTX->interp;
305 struct arm_cti *cti = &obj->cti;
311 Jim_SetResultString(interp, "Wrong numer of args", -1);
315 offset = cti_find_reg_offset(CMD_ARGV[0]);
319 retval = arm_cti_read_reg(cti, offset, &value);
320 if (retval != ERROR_OK)
323 command_print(CMD_CTX, "0x%08"PRIx32, value);
328 static const struct command_registration cti_instance_command_handlers[] = {
331 .mode = COMMAND_EXEC,
332 .handler = handle_cti_dump,
333 .help = "dump CTI registers",
338 .mode = COMMAND_EXEC,
339 .handler = handle_cti_enable,
340 .help = "enable or disable the CTI",
341 .usage = "'on'|'off'",
345 .mode = COMMAND_EXEC,
346 .handler = handle_cti_testmode,
347 .help = "enable or disable integration test mode",
348 .usage = "'on'|'off'",
352 .mode = COMMAND_EXEC,
353 .handler = handle_cti_write,
354 .help = "write to a CTI register",
355 .usage = "register_name value",
359 .mode = COMMAND_EXEC,
360 .handler = handle_cti_read,
361 .help = "read a CTI register",
362 .usage = "register_name",
364 COMMAND_REGISTRATION_DONE
373 static const Jim_Nvp nvp_config_opts[] = {
374 { .name = "-chain-position", .value = CFG_CHAIN_POSITION },
375 { .name = "-ctibase", .value = CFG_CTIBASE },
376 { .name = "-ap-num", .value = CFG_AP_NUM },
377 { .name = NULL, .value = -1 }
380 static int cti_configure(Jim_GetOptInfo *goi, struct arm_cti_object *cti)
382 struct jtag_tap *tap = NULL;
383 struct adiv5_dap *dap;
388 /* parse config or cget options ... */
389 while (goi->argc > 0) {
390 Jim_SetEmptyResult(goi->interp);
392 e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n);
394 Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0);
398 case CFG_CHAIN_POSITION: {
400 e = Jim_GetOpt_Obj(goi, &o_t);
403 tap = jtag_tap_by_jim_obj(goi->interp, o_t);
405 Jim_SetResultString(goi->interp, "-chain-position is invalid", -1);
412 e = Jim_GetOpt_Wide(goi, &w);
415 cti->cti.base = (uint32_t)w;
420 e = Jim_GetOpt_Wide(goi, &w);
423 cti->ap_num = (uint32_t)w;
428 Jim_SetResultString(goi->interp, "-chain-position required when creating CTI", -1);
432 if (tap->dap == NULL) {
439 cti->cti.ap = dap_ap(dap, cti->ap_num);
444 static int cti_create(Jim_GetOptInfo *goi)
446 struct command_context *cmd_ctx;
447 static struct arm_cti_object *cti;
453 cmd_ctx = current_command_context(goi->interp);
454 assert(cmd_ctx != NULL);
457 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
461 Jim_GetOpt_Obj(goi, &new_cmd);
462 /* does this command exist? */
463 cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG);
465 cp = Jim_GetString(new_cmd, NULL);
466 Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
471 cti = calloc(1, sizeof(struct arm_cti_object));
475 e = cti_configure(goi, cti);
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[] = {
495 .help = "cti instance command group",
497 .chain = cti_subcommands,
499 COMMAND_REGISTRATION_DONE
501 e = register_commands(cmd_ctx, NULL, cti_commands);
505 struct command *c = command_find_in_context(cmd_ctx, cp);
507 command_set_handler_data(c, cti);
509 list_add_tail(&cti->lh, &all_cti);
511 return (ERROR_OK == e) ? JIM_OK : JIM_ERR;
514 static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
517 Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
519 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
520 "<name> [<cti_options> ...]");
523 return cti_create(&goi);
526 static int jim_cti_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
528 struct arm_cti_object *obj;
531 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
534 Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
535 list_for_each_entry(obj, &all_cti, lh) {
536 Jim_ListAppendElement(interp, Jim_GetResult(interp),
537 Jim_NewStringObj(interp, obj->name, -1));
543 static const struct command_registration cti_subcommand_handlers[] = {
547 .jim_handler = jim_cti_create,
548 .usage = "name '-chain-position' name [options ...]",
549 .help = "Creates a new CTI object",
554 .jim_handler = jim_cti_names,
556 .help = "Lists all registered CTI objects by name",
558 COMMAND_REGISTRATION_DONE
561 static const struct command_registration cti_command_handlers[] = {
564 .mode = COMMAND_CONFIG,
565 .help = "CTI commands",
566 .chain = cti_subcommand_handlers,
568 COMMAND_REGISTRATION_DONE
571 int cti_register_commands(struct command_context *cmd_ctx)
573 return register_commands(cmd_ctx, NULL, cti_command_handlers);