From 9527d1e595e316a4155c808fafa3a0ea6baa72f2 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Sat, 19 Nov 2016 10:02:34 +0100 Subject: [PATCH] target: generic ARM CTI function wrapper Not specific to ARMv8, the Cross Trigger Interface deserves an independent access wrapper. Change-Id: I84f8faad15ed3515e0fff7f6cc5d1109ef91a869 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3986 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/Makefile.am | 6 +- src/target/arm_cti.c | 148 +++++++++++++++++++++++++++++++++++++++++ src/target/arm_cti.h | 73 ++++++++++++++++++++ 3 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 src/target/arm_cti.c create mode 100644 src/target/arm_cti.h diff --git a/src/target/Makefile.am b/src/target/Makefile.am index e936d3f4..597070c4 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -96,7 +96,8 @@ ARM_DEBUG_SRC = \ %D%/etb.c \ %D%/etm.c \ $(OOCD_TRACE_FILES) \ - %D%/etm_dummy.c + %D%/etm_dummy.c \ + %D%/arm_cti.c AVR32_SRC = \ %D%/avr32_ap7k.c \ @@ -205,6 +206,7 @@ INTEL_IA32_SRC = \ %D%/nds32_v3m.h \ %D%/nds32_aice.h \ %D%/lakemont.h \ - %D%/x86_32_common.h + %D%/x86_32_common.h \ + %D%/arm_cti.h include %D%/openrisc/Makefile.am diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c new file mode 100644 index 00000000..75169b2e --- /dev/null +++ b/src/target/arm_cti.c @@ -0,0 +1,148 @@ +/*************************************************************************** + * 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 +#include +#include "target/arm_adi_v5.h" +#include "target/arm_cti.h" +#include "target/target.h" +#include "helper/time_support.h" + +struct arm_cti { + uint32_t base; + struct adiv5_ap *ap; +}; + +struct arm_cti *arm_cti_create(struct adiv5_ap *ap, uint32_t base) +{ + struct arm_cti *self = calloc(1, sizeof(struct arm_cti)); + if (!self) + return NULL; + + self->base = base; + self->ap = ap; + return self; +} + +static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value) +{ + uint32_t tmp; + + /* Read register */ + int retval = mem_ap_read_atomic_u32(self->ap, self->base + reg, &tmp); + if (ERROR_OK != retval) + return retval; + + /* clear bitfield */ + tmp &= ~mask; + /* put new value */ + tmp |= value & mask; + + /* write new value */ + return mem_ap_write_atomic_u32(self->ap, self->base + reg, tmp); +} + +int arm_cti_enable(struct arm_cti *self, bool enable) +{ + uint32_t val = enable ? 1 : 0; + + return mem_ap_write_atomic_u32(self->ap, self->base + CTI_CTR, val); +} + +int arm_cti_ack_events(struct arm_cti *self, uint32_t event) +{ + int retval; + uint32_t tmp; + + retval = mem_ap_write_atomic_u32(self->ap, self->base + CTI_INACK, event); + if (retval == ERROR_OK) { + int64_t then = timeval_ms(); + for (;;) { + retval = mem_ap_read_atomic_u32(self->ap, self->base + CTI_TROUT_STATUS, &tmp); + 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) +{ + return mem_ap_write_atomic_u32(self->ap, self->base + reg, value); +} + +int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *p_value) +{ + if (p_value == NULL) + return ERROR_COMMAND_ARGUMENT_INVALID; + + return mem_ap_read_atomic_u32(self->ap, self->base + reg, p_value); +} + +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)); +} diff --git a/src/target/arm_cti.h b/src/target/arm_cti.h new file mode 100644 index 00000000..99724c40 --- /dev/null +++ b/src/target/arm_cti.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * 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., * + * * + ***************************************************************************/ + +#ifndef OPENOCD_TARGET_ARM_CTI_H +#define OPENOCD_TARGET_ARM_CTI_H + +/*define CTI(cross trigger interface)*/ +#define CTI_CTR 0x0 +#define CTI_INACK 0x10 +#define CTI_APPSET 0x14 +#define CTI_APPCLEAR 0x18 +#define CTI_APPPULSE 0x1C +#define CTI_INEN0 0x20 +#define CTI_INEN1 0x24 +#define CTI_INEN2 0x28 +#define CTI_INEN3 0x2C +#define CTI_INEN4 0x30 +#define CTI_INEN5 0x34 +#define CTI_INEN6 0x38 +#define CTI_INEN7 0x3C +#define CTI_INEN(n) (0x20 + 4 * n) +#define CTI_OUTEN0 0xA0 +#define CTI_OUTEN1 0xA4 +#define CTI_OUTEN2 0xA8 +#define CTI_OUTEN3 0xAC +#define CTI_OUTEN4 0xB0 +#define CTI_OUTEN5 0xB4 +#define CTI_OUTEN6 0xB8 +#define CTI_OUTEN7 0xBC +#define CTI_OUTEN(n) (0xA0 + 4 * n) +#define CTI_TRIN_STATUS 0x130 +#define CTI_TROUT_STATUS 0x134 +#define CTI_CHIN_STATUS 0x138 +#define CTI_CHOU_STATUS 0x13C +#define CTI_GATE 0x140 +#define CTI_UNLOCK 0xFB0 + +#define CTI_CHNL(x) (1 << x) +#define CTI_TRIG_HALT 0 +#define CTI_TRIG_RESUME 1 +#define CTI_TRIG(n) (1 << CTI_TRIG_##n) + +/* forward-declare arm_cti struct */ +struct arm_cti; + +extern struct arm_cti *arm_cti_create(struct adiv5_ap *ap, uint32_t base); +extern int arm_cti_enable(struct arm_cti *self, bool enable); +extern int arm_cti_ack_events(struct arm_cti *self, uint32_t event); +extern int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel); +extern int arm_cti_ungate_channel(struct arm_cti *self, uint32_t channel); +extern int arm_cti_write_reg(struct arm_cti *self, unsigned int reg, uint32_t value); +extern int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *value); +extern int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel); +extern int arm_cti_set_channel(struct arm_cti *self, uint32_t channel); +extern int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel); + +#endif /* OPENOCD_TARGET_ARM_CTI_H */ -- 2.39.5