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
);
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)