2016-11-19 03:02:34 -06:00
|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2016 by Matthias Welwarsky *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program; if not, write to the *
|
|
|
|
* Free Software Foundation, Inc., *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include "target/arm_adi_v5.h"
|
|
|
|
#include "target/arm_cti.h"
|
|
|
|
#include "target/target.h"
|
|
|
|
#include "helper/time_support.h"
|
2017-04-10 15:53:27 -05:00
|
|
|
#include "helper/list.h"
|
|
|
|
#include "helper/command.h"
|
2016-11-19 03:02:34 -06:00
|
|
|
|
|
|
|
struct arm_cti {
|
2017-04-10 15:53:27 -05:00
|
|
|
struct list_head lh;
|
|
|
|
char *name;
|
2020-10-17 09:27:13 -05:00
|
|
|
struct adiv5_mem_ap_spot spot;
|
2017-04-10 15:53:27 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
static LIST_HEAD(all_cti);
|
|
|
|
|
|
|
|
const char *arm_cti_name(struct arm_cti *self)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
return self->name;
|
2017-04-10 15:53:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
|
2016-11-19 03:02:34 -06:00
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct arm_cti *obj = NULL;
|
2017-04-10 15:53:27 -05:00
|
|
|
const char *name;
|
|
|
|
bool found = false;
|
2016-11-19 03:02:34 -06:00
|
|
|
|
2017-04-10 15:53:27 -05:00
|
|
|
name = Jim_GetString(o, NULL);
|
|
|
|
|
|
|
|
list_for_each_entry(obj, &all_cti, lh) {
|
|
|
|
if (!strcmp(name, obj->name)) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found)
|
2020-10-17 09:27:13 -05:00
|
|
|
return obj;
|
2017-04-10 15:53:27 -05:00
|
|
|
return NULL;
|
2016-11-19 03:02:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num);
|
2016-11-19 03:02:34 -06:00
|
|
|
uint32_t tmp;
|
|
|
|
|
|
|
|
/* Read register */
|
2020-10-17 09:27:13 -05:00
|
|
|
int retval = mem_ap_read_atomic_u32(ap, self->spot.base + reg, &tmp);
|
2021-07-03 09:47:35 -05:00
|
|
|
if (retval != ERROR_OK)
|
2016-11-19 03:02:34 -06:00
|
|
|
return retval;
|
|
|
|
|
|
|
|
/* clear bitfield */
|
|
|
|
tmp &= ~mask;
|
|
|
|
/* put new value */
|
|
|
|
tmp |= value & mask;
|
|
|
|
|
|
|
|
/* write new value */
|
2020-10-17 09:27:13 -05:00
|
|
|
return mem_ap_write_atomic_u32(ap, self->spot.base + reg, tmp);
|
2016-11-19 03:02:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
int arm_cti_enable(struct arm_cti *self, bool enable)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num);
|
2016-11-19 03:02:34 -06:00
|
|
|
uint32_t val = enable ? 1 : 0;
|
|
|
|
|
2020-10-17 09:27:13 -05:00
|
|
|
return mem_ap_write_atomic_u32(ap, self->spot.base + CTI_CTR, val);
|
2016-11-19 03:02:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
int arm_cti_ack_events(struct arm_cti *self, uint32_t event)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num);
|
2016-11-19 03:02:34 -06:00
|
|
|
int retval;
|
|
|
|
uint32_t tmp;
|
|
|
|
|
2020-10-17 09:27:13 -05:00
|
|
|
retval = mem_ap_write_atomic_u32(ap, self->spot.base + CTI_INACK, event);
|
2016-11-19 03:02:34 -06:00
|
|
|
if (retval == ERROR_OK) {
|
|
|
|
int64_t then = timeval_ms();
|
|
|
|
for (;;) {
|
2020-10-17 09:27:13 -05:00
|
|
|
retval = mem_ap_read_atomic_u32(ap, self->spot.base + CTI_TROUT_STATUS, &tmp);
|
2016-11-19 03:02:34 -06:00
|
|
|
if (retval != ERROR_OK)
|
|
|
|
break;
|
|
|
|
if ((tmp & event) == 0)
|
|
|
|
break;
|
|
|
|
if (timeval_ms() > then + 1000) {
|
|
|
|
LOG_ERROR("timeout waiting for target");
|
|
|
|
retval = ERROR_TARGET_TIMEOUT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel)
|
|
|
|
{
|
|
|
|
if (channel > 31)
|
|
|
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
|
|
|
|
|
|
|
return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int arm_cti_ungate_channel(struct arm_cti *self, uint32_t channel)
|
|
|
|
{
|
|
|
|
if (channel > 31)
|
|
|
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
|
|
|
|
|
|
|
return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0xFFFFFFFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
int arm_cti_write_reg(struct arm_cti *self, unsigned int reg, uint32_t value)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num);
|
|
|
|
|
|
|
|
return mem_ap_write_atomic_u32(ap, self->spot.base + reg, value);
|
2016-11-19 03:02:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *p_value)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num);
|
|
|
|
|
2021-07-03 11:51:20 -05:00
|
|
|
if (!p_value)
|
2016-11-19 03:02:34 -06:00
|
|
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
|
|
|
|
2020-10-17 09:27:13 -05:00
|
|
|
return mem_ap_read_atomic_u32(ap, self->spot.base + reg, p_value);
|
2016-11-19 03:02:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel)
|
|
|
|
{
|
|
|
|
if (channel > 31)
|
|
|
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
|
|
|
|
|
|
|
return arm_cti_write_reg(self, CTI_APPPULSE, CTI_CHNL(channel));
|
|
|
|
}
|
|
|
|
|
|
|
|
int arm_cti_set_channel(struct arm_cti *self, uint32_t channel)
|
|
|
|
{
|
|
|
|
if (channel > 31)
|
|
|
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
|
|
|
|
|
|
|
return arm_cti_write_reg(self, CTI_APPSET, CTI_CHNL(channel));
|
|
|
|
}
|
|
|
|
|
|
|
|
int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel)
|
|
|
|
{
|
|
|
|
if (channel > 31)
|
|
|
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
|
|
|
|
|
|
|
return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel));
|
|
|
|
}
|
2017-04-10 15:53:27 -05:00
|
|
|
|
2018-12-20 12:10:17 -06:00
|
|
|
static uint32_t cti_regs[28];
|
2017-04-10 15:53:27 -05:00
|
|
|
|
|
|
|
static const struct {
|
|
|
|
uint32_t offset;
|
|
|
|
const char *label;
|
|
|
|
uint32_t *p_val;
|
|
|
|
} cti_names[] = {
|
|
|
|
{ CTI_CTR, "CTR", &cti_regs[0] },
|
|
|
|
{ CTI_GATE, "GATE", &cti_regs[1] },
|
|
|
|
{ CTI_INEN0, "INEN0", &cti_regs[2] },
|
|
|
|
{ CTI_INEN1, "INEN1", &cti_regs[3] },
|
|
|
|
{ CTI_INEN2, "INEN2", &cti_regs[4] },
|
|
|
|
{ CTI_INEN3, "INEN3", &cti_regs[5] },
|
|
|
|
{ CTI_INEN4, "INEN4", &cti_regs[6] },
|
|
|
|
{ CTI_INEN5, "INEN5", &cti_regs[7] },
|
|
|
|
{ CTI_INEN6, "INEN6", &cti_regs[8] },
|
|
|
|
{ CTI_INEN7, "INEN7", &cti_regs[9] },
|
|
|
|
{ CTI_INEN8, "INEN8", &cti_regs[10] },
|
|
|
|
{ CTI_OUTEN0, "OUTEN0", &cti_regs[11] },
|
|
|
|
{ CTI_OUTEN1, "OUTEN1", &cti_regs[12] },
|
|
|
|
{ CTI_OUTEN2, "OUTEN2", &cti_regs[13] },
|
|
|
|
{ CTI_OUTEN3, "OUTEN3", &cti_regs[14] },
|
|
|
|
{ CTI_OUTEN4, "OUTEN4", &cti_regs[15] },
|
|
|
|
{ CTI_OUTEN5, "OUTEN5", &cti_regs[16] },
|
|
|
|
{ CTI_OUTEN6, "OUTEN6", &cti_regs[17] },
|
|
|
|
{ CTI_OUTEN7, "OUTEN7", &cti_regs[18] },
|
|
|
|
{ CTI_OUTEN8, "OUTEN8", &cti_regs[19] },
|
|
|
|
{ CTI_TRIN_STATUS, "TRIN", &cti_regs[20] },
|
|
|
|
{ CTI_TROUT_STATUS, "TROUT", &cti_regs[21] },
|
|
|
|
{ CTI_CHIN_STATUS, "CHIN", &cti_regs[22] },
|
|
|
|
{ CTI_CHOU_STATUS, "CHOUT", &cti_regs[23] },
|
|
|
|
{ CTI_APPSET, "APPSET", &cti_regs[24] },
|
|
|
|
{ CTI_APPCLEAR, "APPCLR", &cti_regs[25] },
|
2018-12-20 12:10:17 -06:00
|
|
|
{ CTI_APPPULSE, "APPPULSE", &cti_regs[26] },
|
|
|
|
{ CTI_INACK, "INACK", &cti_regs[27] },
|
2017-04-10 15:53:27 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
static int cti_find_reg_offset(const char *name)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(cti_names); i++) {
|
|
|
|
if (!strcmp(name, cti_names[i].label))
|
|
|
|
return cti_names[i].offset;
|
|
|
|
}
|
2018-12-20 12:33:26 -06:00
|
|
|
|
|
|
|
LOG_ERROR("unknown CTI register %s", name);
|
2017-04-10 15:53:27 -05:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-03-26 02:45:46 -05:00
|
|
|
int arm_cti_cleanup_all(void)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct arm_cti *obj, *tmp;
|
2018-03-26 02:45:46 -05:00
|
|
|
|
|
|
|
list_for_each_entry_safe(obj, tmp, &all_cti, lh) {
|
|
|
|
free(obj->name);
|
|
|
|
free(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2017-04-10 15:53:27 -05:00
|
|
|
COMMAND_HANDLER(handle_cti_dump)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct arm_cti *cti = CMD_DATA;
|
|
|
|
struct adiv5_ap *ap = dap_ap(cti->spot.dap, cti->spot.ap_num);
|
2017-04-10 15:53:27 -05:00
|
|
|
int retval = ERROR_OK;
|
|
|
|
|
|
|
|
for (int i = 0; (retval == ERROR_OK) && (i < (int)ARRAY_SIZE(cti_names)); i++)
|
2020-10-17 09:27:13 -05:00
|
|
|
retval = mem_ap_read_u32(ap,
|
|
|
|
cti->spot.base + cti_names[i].offset, cti_names[i].p_val);
|
2017-04-10 15:53:27 -05:00
|
|
|
|
|
|
|
if (retval == ERROR_OK)
|
2020-10-17 09:27:13 -05:00
|
|
|
retval = dap_run(ap->dap);
|
2017-04-10 15:53:27 -05:00
|
|
|
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return JIM_ERR;
|
|
|
|
|
|
|
|
for (int i = 0; i < (int)ARRAY_SIZE(cti_names); i++)
|
helper/command: change prototype of command_print/command_print_sameline
To prepare for handling TCL return values consistently, all calls
to command_print/command_print_sameline should switch to CMD as
first parameter.
Change prototype of command_print() and command_print_sameline()
to pass CMD instead of CMD_CTX.
Since the first parameter is currently not used, the change can be
done though scripts without manual coding.
This patch is created using the command:
sed -i PATTERN $(find src/ doc/ -type f)
with all the following patters:
's/\(command_print(cmd\)->ctx,/\1,/'
's/\(command_print(CMD\)_CTX,/\1,/'
's/\(command_print(struct command_\)context \*context,/\1invocation *cmd,/'
's/\(command_print_sameline(cmd\)->ctx,/\1,/'
's/\(command_print_sameline(CMD\)_CTX,/\1,/'
's/\(command_print_sameline(struct command_\)context \*context,/\1invocation *cmd,/'
This change is inspired by http://openocd.zylin.com/1815 from Paul
Fertser but is now done through scripting.
Change-Id: I3386d8f96cdc477e7a2308dd18269de3bed04385
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Reviewed-on: http://openocd.zylin.com/5081
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
2019-04-03 03:37:24 -05:00
|
|
|
command_print(CMD, "%8.8s (0x%04"PRIx32") 0x%08"PRIx32,
|
2017-04-10 15:53:27 -05:00
|
|
|
cti_names[i].label, cti_names[i].offset, *cti_names[i].p_val);
|
|
|
|
|
|
|
|
return JIM_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
COMMAND_HANDLER(handle_cti_enable)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct arm_cti *cti = CMD_DATA;
|
2017-04-10 15:53:27 -05:00
|
|
|
bool on_off;
|
|
|
|
|
2019-12-16 06:08:01 -06:00
|
|
|
if (CMD_ARGC != 1)
|
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
2017-04-10 15:53:27 -05:00
|
|
|
|
|
|
|
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
|
|
|
|
|
|
|
|
return arm_cti_enable(cti, on_off);
|
|
|
|
}
|
|
|
|
|
|
|
|
COMMAND_HANDLER(handle_cti_testmode)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct arm_cti *cti = CMD_DATA;
|
2017-04-10 15:53:27 -05:00
|
|
|
bool on_off;
|
|
|
|
|
2019-12-16 06:08:01 -06:00
|
|
|
if (CMD_ARGC != 1)
|
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
2017-04-10 15:53:27 -05:00
|
|
|
|
|
|
|
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
|
|
|
|
|
|
|
|
return arm_cti_write_reg(cti, 0xf00, on_off ? 0x1 : 0x0);
|
|
|
|
}
|
|
|
|
|
|
|
|
COMMAND_HANDLER(handle_cti_write)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct arm_cti *cti = CMD_DATA;
|
2017-04-10 15:53:27 -05:00
|
|
|
int offset;
|
|
|
|
uint32_t value;
|
|
|
|
|
2019-12-16 06:08:01 -06:00
|
|
|
if (CMD_ARGC != 2)
|
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
2017-04-10 15:53:27 -05:00
|
|
|
|
|
|
|
offset = cti_find_reg_offset(CMD_ARGV[0]);
|
|
|
|
if (offset < 0)
|
|
|
|
return ERROR_FAIL;
|
|
|
|
|
|
|
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
|
|
|
|
|
|
|
return arm_cti_write_reg(cti, offset, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
COMMAND_HANDLER(handle_cti_read)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct arm_cti *cti = CMD_DATA;
|
2017-04-10 15:53:27 -05:00
|
|
|
int offset;
|
|
|
|
int retval;
|
|
|
|
uint32_t value;
|
|
|
|
|
2019-12-16 06:08:01 -06:00
|
|
|
if (CMD_ARGC != 1)
|
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
2017-04-10 15:53:27 -05:00
|
|
|
|
|
|
|
offset = cti_find_reg_offset(CMD_ARGV[0]);
|
|
|
|
if (offset < 0)
|
|
|
|
return ERROR_FAIL;
|
|
|
|
|
|
|
|
retval = arm_cti_read_reg(cti, offset, &value);
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
|
helper/command: change prototype of command_print/command_print_sameline
To prepare for handling TCL return values consistently, all calls
to command_print/command_print_sameline should switch to CMD as
first parameter.
Change prototype of command_print() and command_print_sameline()
to pass CMD instead of CMD_CTX.
Since the first parameter is currently not used, the change can be
done though scripts without manual coding.
This patch is created using the command:
sed -i PATTERN $(find src/ doc/ -type f)
with all the following patters:
's/\(command_print(cmd\)->ctx,/\1,/'
's/\(command_print(CMD\)_CTX,/\1,/'
's/\(command_print(struct command_\)context \*context,/\1invocation *cmd,/'
's/\(command_print_sameline(cmd\)->ctx,/\1,/'
's/\(command_print_sameline(CMD\)_CTX,/\1,/'
's/\(command_print_sameline(struct command_\)context \*context,/\1invocation *cmd,/'
This change is inspired by http://openocd.zylin.com/1815 from Paul
Fertser but is now done through scripting.
Change-Id: I3386d8f96cdc477e7a2308dd18269de3bed04385
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Reviewed-on: http://openocd.zylin.com/5081
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
2019-04-03 03:37:24 -05:00
|
|
|
command_print(CMD, "0x%08"PRIx32, value);
|
2017-04-10 15:53:27 -05:00
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2019-12-16 09:05:17 -06:00
|
|
|
COMMAND_HANDLER(handle_cti_ack)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct arm_cti *cti = CMD_DATA;
|
2019-12-16 09:05:17 -06:00
|
|
|
uint32_t event;
|
|
|
|
|
|
|
|
if (CMD_ARGC != 1)
|
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
|
|
|
|
|
|
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], event);
|
|
|
|
|
|
|
|
int retval = arm_cti_ack_events(cti, 1 << event);
|
|
|
|
|
|
|
|
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
COMMAND_HANDLER(handle_cti_channel)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct arm_cti *cti = CMD_DATA;
|
2019-12-16 09:05:17 -06:00
|
|
|
int retval = ERROR_OK;
|
|
|
|
uint32_t ch_num;
|
|
|
|
|
|
|
|
if (CMD_ARGC != 2)
|
|
|
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
|
|
|
|
|
|
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], ch_num);
|
|
|
|
|
|
|
|
if (!strcmp(CMD_ARGV[1], "gate"))
|
|
|
|
retval = arm_cti_gate_channel(cti, ch_num);
|
|
|
|
else if (!strcmp(CMD_ARGV[1], "ungate"))
|
|
|
|
retval = arm_cti_ungate_channel(cti, ch_num);
|
|
|
|
else if (!strcmp(CMD_ARGV[1], "pulse"))
|
|
|
|
retval = arm_cti_pulse_channel(cti, ch_num);
|
|
|
|
else if (!strcmp(CMD_ARGV[1], "set"))
|
|
|
|
retval = arm_cti_set_channel(cti, ch_num);
|
|
|
|
else if (!strcmp(CMD_ARGV[1], "clear"))
|
|
|
|
retval = arm_cti_clear_channel(cti, ch_num);
|
|
|
|
else {
|
|
|
|
command_print(CMD, "Possible channel operations: gate|ungate|set|clear|pulse");
|
|
|
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2017-04-10 15:53:27 -05:00
|
|
|
static const struct command_registration cti_instance_command_handlers[] = {
|
|
|
|
{
|
|
|
|
.name = "dump",
|
|
|
|
.mode = COMMAND_EXEC,
|
|
|
|
.handler = handle_cti_dump,
|
|
|
|
.help = "dump CTI registers",
|
|
|
|
.usage = "",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "enable",
|
|
|
|
.mode = COMMAND_EXEC,
|
|
|
|
.handler = handle_cti_enable,
|
|
|
|
.help = "enable or disable the CTI",
|
|
|
|
.usage = "'on'|'off'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "testmode",
|
|
|
|
.mode = COMMAND_EXEC,
|
|
|
|
.handler = handle_cti_testmode,
|
|
|
|
.help = "enable or disable integration test mode",
|
|
|
|
.usage = "'on'|'off'",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "write",
|
|
|
|
.mode = COMMAND_EXEC,
|
|
|
|
.handler = handle_cti_write,
|
|
|
|
.help = "write to a CTI register",
|
|
|
|
.usage = "register_name value",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "read",
|
|
|
|
.mode = COMMAND_EXEC,
|
|
|
|
.handler = handle_cti_read,
|
|
|
|
.help = "read a CTI register",
|
|
|
|
.usage = "register_name",
|
|
|
|
},
|
2019-12-16 09:05:17 -06:00
|
|
|
{
|
|
|
|
.name = "ack",
|
|
|
|
.mode = COMMAND_EXEC,
|
|
|
|
.handler = handle_cti_ack,
|
|
|
|
.help = "acknowledge a CTI event",
|
|
|
|
.usage = "event",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "channel",
|
|
|
|
.mode = COMMAND_EXEC,
|
|
|
|
.handler = handle_cti_channel,
|
|
|
|
.help = "do an operation on one CTI channel, possible operations: "
|
|
|
|
"gate, ungate, set, clear and pulse",
|
|
|
|
.usage = "channel_number operation",
|
|
|
|
},
|
2017-04-10 15:53:27 -05:00
|
|
|
COMMAND_REGISTRATION_DONE
|
|
|
|
};
|
|
|
|
|
2021-04-24 17:48:14 -05:00
|
|
|
static int cti_configure(struct jim_getopt_info *goi, struct arm_cti *cti)
|
2017-04-10 15:53:27 -05:00
|
|
|
{
|
|
|
|
/* parse config or cget options ... */
|
|
|
|
while (goi->argc > 0) {
|
2020-10-17 09:27:13 -05:00
|
|
|
int e = adiv5_jim_mem_ap_spot_configure(&cti->spot, goi);
|
2022-04-23 06:13:06 -05:00
|
|
|
|
|
|
|
if (e == JIM_CONTINUE)
|
|
|
|
Jim_SetResultFormatted(goi->interp, "unknown option '%s'",
|
|
|
|
Jim_String(goi->argv[0]));
|
|
|
|
|
2020-10-17 09:27:13 -05:00
|
|
|
if (e != JIM_OK)
|
2022-04-23 06:13:06 -05:00
|
|
|
return JIM_ERR;
|
2017-04-10 15:53:27 -05:00
|
|
|
}
|
|
|
|
|
2020-10-17 09:27:13 -05:00
|
|
|
if (!cti->spot.dap) {
|
2018-03-23 15:17:29 -05:00
|
|
|
Jim_SetResultString(goi->interp, "-dap required when creating CTI", -1);
|
2017-04-10 15:53:27 -05:00
|
|
|
return JIM_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return JIM_OK;
|
|
|
|
}
|
2021-04-24 17:48:14 -05:00
|
|
|
static int cti_create(struct jim_getopt_info *goi)
|
2017-04-10 15:53:27 -05:00
|
|
|
{
|
|
|
|
struct command_context *cmd_ctx;
|
2020-10-17 09:27:13 -05:00
|
|
|
static struct arm_cti *cti;
|
2017-04-10 15:53:27 -05:00
|
|
|
Jim_Obj *new_cmd;
|
|
|
|
Jim_Cmd *cmd;
|
|
|
|
const char *cp;
|
|
|
|
int e;
|
|
|
|
|
|
|
|
cmd_ctx = current_command_context(goi->interp);
|
2021-07-03 11:51:20 -05:00
|
|
|
assert(cmd_ctx);
|
2017-04-10 15:53:27 -05:00
|
|
|
|
|
|
|
if (goi->argc < 3) {
|
|
|
|
Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
|
|
|
|
return JIM_ERR;
|
|
|
|
}
|
|
|
|
/* COMMAND */
|
2021-04-24 17:48:14 -05:00
|
|
|
jim_getopt_obj(goi, &new_cmd);
|
2017-04-10 15:53:27 -05:00
|
|
|
/* does this command exist? */
|
2021-09-17 11:37:41 -05:00
|
|
|
cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
|
2017-04-10 15:53:27 -05:00
|
|
|
if (cmd) {
|
|
|
|
cp = Jim_GetString(new_cmd, NULL);
|
|
|
|
Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
|
|
|
|
return JIM_ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create it */
|
2020-10-17 09:27:13 -05:00
|
|
|
cti = calloc(1, sizeof(*cti));
|
2021-07-03 11:51:20 -05:00
|
|
|
if (!cti)
|
2017-04-10 15:53:27 -05:00
|
|
|
return JIM_ERR;
|
|
|
|
|
2020-10-17 09:27:13 -05:00
|
|
|
adiv5_mem_ap_spot_init(&cti->spot);
|
|
|
|
|
|
|
|
/* Do the rest as "configure" options */
|
|
|
|
goi->isconfigure = 1;
|
2017-04-10 15:53:27 -05:00
|
|
|
e = cti_configure(goi, cti);
|
|
|
|
if (e != JIM_OK) {
|
|
|
|
free(cti);
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = Jim_GetString(new_cmd, NULL);
|
|
|
|
cti->name = strdup(cp);
|
|
|
|
|
|
|
|
/* now - create the new cti name command */
|
|
|
|
const struct command_registration cti_subcommands[] = {
|
|
|
|
{
|
|
|
|
.chain = cti_instance_command_handlers,
|
|
|
|
},
|
|
|
|
COMMAND_REGISTRATION_DONE
|
|
|
|
};
|
|
|
|
const struct command_registration cti_commands[] = {
|
|
|
|
{
|
|
|
|
.name = cp,
|
|
|
|
.mode = COMMAND_ANY,
|
|
|
|
.help = "cti instance command group",
|
|
|
|
.usage = "",
|
|
|
|
.chain = cti_subcommands,
|
|
|
|
},
|
|
|
|
COMMAND_REGISTRATION_DONE
|
|
|
|
};
|
2020-05-12 04:52:56 -05:00
|
|
|
e = register_commands_with_data(cmd_ctx, NULL, cti_commands, cti);
|
2021-07-03 09:47:35 -05:00
|
|
|
if (e != ERROR_OK)
|
2017-04-10 15:53:27 -05:00
|
|
|
return JIM_ERR;
|
|
|
|
|
|
|
|
list_add_tail(&cti->lh, &all_cti);
|
|
|
|
|
2020-05-12 04:52:56 -05:00
|
|
|
return JIM_OK;
|
2017-04-10 15:53:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
|
|
|
{
|
2021-04-24 17:48:14 -05:00
|
|
|
struct jim_getopt_info goi;
|
|
|
|
jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
|
2017-04-10 15:53:27 -05:00
|
|
|
if (goi.argc < 2) {
|
|
|
|
Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
|
|
|
|
"<name> [<cti_options> ...]");
|
|
|
|
return JIM_ERR;
|
|
|
|
}
|
|
|
|
return cti_create(&goi);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int jim_cti_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
|
|
|
{
|
2020-10-17 09:27:13 -05:00
|
|
|
struct arm_cti *obj;
|
2017-04-10 15:53:27 -05:00
|
|
|
|
|
|
|
if (argc != 1) {
|
|
|
|
Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
|
|
|
|
return JIM_ERR;
|
|
|
|
}
|
|
|
|
Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
|
|
|
|
list_for_each_entry(obj, &all_cti, lh) {
|
|
|
|
Jim_ListAppendElement(interp, Jim_GetResult(interp),
|
|
|
|
Jim_NewStringObj(interp, obj->name, -1));
|
|
|
|
}
|
|
|
|
return JIM_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const struct command_registration cti_subcommand_handlers[] = {
|
|
|
|
{
|
|
|
|
.name = "create",
|
|
|
|
.mode = COMMAND_ANY,
|
|
|
|
.jim_handler = jim_cti_create,
|
|
|
|
.usage = "name '-chain-position' name [options ...]",
|
|
|
|
.help = "Creates a new CTI object",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "names",
|
|
|
|
.mode = COMMAND_ANY,
|
|
|
|
.jim_handler = jim_cti_names,
|
|
|
|
.usage = "",
|
|
|
|
.help = "Lists all registered CTI objects by name",
|
|
|
|
},
|
|
|
|
COMMAND_REGISTRATION_DONE
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct command_registration cti_command_handlers[] = {
|
|
|
|
{
|
|
|
|
.name = "cti",
|
|
|
|
.mode = COMMAND_CONFIG,
|
|
|
|
.help = "CTI commands",
|
|
|
|
.chain = cti_subcommand_handlers,
|
2019-01-04 08:13:53 -06:00
|
|
|
.usage = "",
|
2017-04-10 15:53:27 -05:00
|
|
|
},
|
|
|
|
COMMAND_REGISTRATION_DONE
|
|
|
|
};
|
|
|
|
|
|
|
|
int cti_register_commands(struct command_context *cmd_ctx)
|
|
|
|
{
|
|
|
|
return register_commands(cmd_ctx, NULL, cti_command_handlers);
|
|
|
|
}
|