1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2016 by Matthias Welwarsky *
6 ***************************************************************************/
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"
24 struct adiv5_mem_ap_spot spot
;
28 static LIST_HEAD(all_cti
);
30 const char *arm_cti_name(struct arm_cti
*self
)
35 struct arm_cti
*cti_instance_by_jim_obj(Jim_Interp
*interp
, Jim_Obj
*o
)
37 struct arm_cti
*obj
= NULL
;
41 name
= Jim_GetString(o
, NULL
);
43 list_for_each_entry(obj
, &all_cti
, lh
) {
44 if (!strcmp(name
, obj
->name
)) {
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
;
61 int retval
= mem_ap_read_atomic_u32(ap
, self
->spot
.base
+ reg
, &tmp
);
62 if (retval
!= ERROR_OK
)
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
;
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();
91 retval
= mem_ap_read_atomic_u32(ap
, self
->spot
.base
+ CTI_TROUT_STATUS
, &tmp
);
92 if (retval
!= ERROR_OK
)
94 if ((tmp
& event
) == 0)
96 if (timeval_ms() > then
+ 1000) {
97 LOG_ERROR("timeout waiting for target");
98 retval
= ERROR_TARGET_TIMEOUT
;
107 int arm_cti_gate_channel(struct arm_cti
*self
, uint32_t channel
)
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
)
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
)
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
)
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
)
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
)
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 {
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
)
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
);
210 int arm_cti_cleanup_all(void)
212 struct arm_cti
*obj
, *tmp
;
214 list_for_each_entry_safe(obj
, tmp
, &all_cti
, lh
) {
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
)
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
);
247 COMMAND_HANDLER(handle_cti_enable
)
249 struct arm_cti
*cti
= CMD_DATA
;
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
;
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
;
280 return ERROR_COMMAND_SYNTAX_ERROR
;
282 offset
= cti_find_reg_offset(CMD_ARGV
[0]);
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
;
299 return ERROR_COMMAND_SYNTAX_ERROR
;
301 offset
= cti_find_reg_offset(CMD_ARGV
[0]);
305 retval
= arm_cti_read_reg(cti
, offset
, &value
);
306 if (retval
!= ERROR_OK
)
309 command_print(CMD
, "0x%08"PRIx32
, value
);
314 COMMAND_HANDLER(handle_cti_ack
)
316 struct arm_cti
*cti
= CMD_DATA
;
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
)
333 COMMAND_HANDLER(handle_cti_channel
)
335 struct arm_cti
*cti
= CMD_DATA
;
336 int retval
= ERROR_OK
;
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
);
355 command_print(CMD
, "Possible channel operations: gate|ungate|set|clear|pulse");
356 return ERROR_COMMAND_ARGUMENT_INVALID
;
359 if (retval
!= ERROR_OK
)
365 static const struct command_registration cti_instance_command_handlers
[] = {
368 .mode
= COMMAND_EXEC
,
369 .handler
= handle_cti_dump
,
370 .help
= "dump CTI registers",
375 .mode
= COMMAND_EXEC
,
376 .handler
= handle_cti_enable
,
377 .help
= "enable or disable the CTI",
378 .usage
= "'on'|'off'",
382 .mode
= COMMAND_EXEC
,
383 .handler
= handle_cti_testmode
,
384 .help
= "enable or disable integration test mode",
385 .usage
= "'on'|'off'",
389 .mode
= COMMAND_EXEC
,
390 .handler
= handle_cti_write
,
391 .help
= "write to a CTI register",
392 .usage
= "register_name value",
396 .mode
= COMMAND_EXEC
,
397 .handler
= handle_cti_read
,
398 .help
= "read a CTI register",
399 .usage
= "register_name",
403 .mode
= COMMAND_EXEC
,
404 .handler
= handle_cti_ack
,
405 .help
= "acknowledge a CTI event",
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]));
433 if (!cti
->spot
.dap
) {
434 Jim_SetResultString(goi
->interp
, "-dap required when creating CTI", -1);
440 static int cti_create(struct jim_getopt_info
*goi
)
442 struct command_context
*cmd_ctx
;
443 static struct arm_cti
*cti
;
449 cmd_ctx
= current_command_context(goi
->interp
);
453 Jim_WrongNumArgs(goi
->interp
, 1, goi
->argv
, "?name? ..options...");
457 jim_getopt_obj(goi
, &new_cmd
);
458 /* does this command exist? */
459 cmd
= Jim_GetCommand(goi
->interp
, new_cmd
, JIM_NONE
);
461 cp
= Jim_GetString(new_cmd
, NULL
);
462 Jim_SetResultFormatted(goi
->interp
, "Command: %s Exists", cp
);
467 cti
= calloc(1, sizeof(*cti
));
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
);
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_with_data(cmd_ctx
, NULL
, cti_commands
, cti
);
505 list_add_tail(&cti
->lh
, &all_cti
);
507 cti
->ap
= dap_get_ap(cti
->spot
.dap
, cti
->spot
.ap_num
);
509 Jim_SetResultString(goi
->interp
, "Cannot get AP", -1);
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);
521 Jim_WrongNumArgs(goi
.interp
, goi
.argc
, goi
.argv
,
522 "<name> [<cti_options> ...]");
525 return cti_create(&goi
);
528 COMMAND_HANDLER(cti_handle_names
)
533 return ERROR_COMMAND_SYNTAX_ERROR
;
535 list_for_each_entry(obj
, &all_cti
, lh
)
536 command_print(CMD
, "%s", obj
->name
);
542 static const struct command_registration cti_subcommand_handlers
[] = {
546 .jim_handler
= jim_cti_create
,
547 .usage
= "name '-chain-position' name [options ...]",
548 .help
= "Creates a new CTI object",
553 .handler
= cti_handle_names
,
555 .help
= "Lists all registered CTI objects by name",
557 COMMAND_REGISTRATION_DONE
560 static const struct command_registration cti_command_handlers
[] = {
563 .mode
= COMMAND_CONFIG
,
564 .help
= "CTI commands",
565 .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
);