coresight: add etm3 device support
Signed-off-by: liaoao <liaoao@xiaomi.com>
This commit is contained in:
parent
e3e23f7eaf
commit
71e4267a7a
@ -21,6 +21,10 @@
|
||||
if(CONFIG_CORESIGHT)
|
||||
set(SRCS coresight_core.c coresight_common.c)
|
||||
|
||||
if(CONFIG_CORESIGHT_ETM_VERSION STREQUAL "v3")
|
||||
list(APPEND SRCS coresight_etm3.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_CORESIGHT_FUNNEL)
|
||||
list(APPEND SRCS coresight_funnel.c)
|
||||
endif()
|
||||
|
@ -19,6 +19,22 @@ config CORESIGHT_TIMEOUT
|
||||
int "Timeout us for waiting register state change"
|
||||
default 100
|
||||
|
||||
config CORESIGHT_ETM
|
||||
bool "ETM coresight device support"
|
||||
default n
|
||||
|
||||
if CORESIGHT_ETM
|
||||
|
||||
config CORESIGHT_ETM_VERSION
|
||||
string "Coresight ETM version"
|
||||
default "v3"
|
||||
|
||||
config CORESIGHT_ETM_USE_COPROCESSOR
|
||||
bool "Whether use coprocessor to access ETM registers"
|
||||
default n
|
||||
|
||||
endif # CORESIGHT_ETM
|
||||
|
||||
config CORESIGHT_FUNNEL
|
||||
bool "Funnel coresight device support"
|
||||
default n
|
||||
|
@ -24,6 +24,10 @@ ifeq ($(CONFIG_CORESIGHT),y)
|
||||
|
||||
CSRCS += coresight_core.c coresight_common.c
|
||||
|
||||
ifeq ($(CONFIG_CORESIGHT_ETM_VERSION),"v3")
|
||||
CSRCS += coresight_etm3.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CORESIGHT_FUNNEL),y)
|
||||
CSRCS += coresight_funnel.c
|
||||
endif
|
||||
|
@ -272,15 +272,14 @@ void coresight_put_system_trace_id(int traceid)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int coresight_timeout(uintptr_t addr, uint32_t off,
|
||||
uint32_t bitmask, uint32_t val)
|
||||
int coresight_timeout(uint32_t val, uint32_t mask, uintptr_t addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = CONFIG_CORESIGHT_TIMEOUT; i > 0; i--)
|
||||
{
|
||||
uint32_t value = coresight_get32(addr + off);
|
||||
if ((value & bitmask) == val)
|
||||
uint32_t value = coresight_get32(addr);
|
||||
if ((value & mask) == val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -183,8 +183,7 @@ void coresight_put_system_trace_id(int traceid);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int coresight_timeout(uintptr_t addr, uint32_t off,
|
||||
uint32_t bitmask, uint32_t val);
|
||||
int coresight_timeout(uint32_t val, uint32_t mask, uintptr_t addr);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: coresight_insert_barrier_packet
|
||||
|
733
drivers/coresight/coresight_etm3.c
Normal file
733
drivers/coresight/coresight_etm3.c
Normal file
@ -0,0 +1,733 @@
|
||||
/****************************************************************************
|
||||
* drivers/coresight/coresight_etm3.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <nuttx/bits.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include <nuttx/coresight/coresight_etm.h>
|
||||
|
||||
#include "coresight_common.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Device registers:
|
||||
* 0x000 - 0x2FC: Trace registers
|
||||
* 0x300 - 0x314: Management registers
|
||||
* 0x318 - 0xEFC: Trace registers
|
||||
*
|
||||
* Coresight registers
|
||||
* 0xF00 - 0xF9C: Management registers
|
||||
* 0xFA0 - 0xFA4: Management registers in PFTv1.0
|
||||
* Trace registers in PFTv1.1
|
||||
* 0xFA8 - 0xFFC: Management registers
|
||||
*/
|
||||
|
||||
#define ETM_CR 0x000
|
||||
#define ETM_CCR 0x004
|
||||
#define ETM_TRIGGER 0x008
|
||||
#define ETM_SR 0x010
|
||||
#define ETM_SCR 0x014
|
||||
#define ETM_TSSCR 0x018
|
||||
#define ETM_TECR2 0x01c
|
||||
#define ETM_TEEVR 0x020
|
||||
#define ETM_TECR1 0x024
|
||||
#define ETM_FFLR 0x02c
|
||||
#define ETM_ACVR(n) (0x040 + (n * 4))
|
||||
#define ETM_ACTR(n) (0x080 + (n * 4))
|
||||
#define ETM_CNTRLDVR(n) (0x140 + (n * 4))
|
||||
#define ETM_CNTENR(n) (0x150 + (n * 4))
|
||||
#define ETM_CNTRLDEVR(n) (0x160 + (n * 4))
|
||||
#define ETM_CNTVR(n) (0x170 + (n * 4))
|
||||
#define ETM_SQ12EVR 0x180
|
||||
#define ETM_SQ21EVR 0x184
|
||||
#define ETM_SQ23EVR 0x188
|
||||
#define ETM_SQ31EVR 0x18c
|
||||
#define ETM_SQ32EVR 0x190
|
||||
#define ETM_SQ13EVR 0x194
|
||||
#define ETM_SQR 0x19c
|
||||
#define ETM_EXTOUTEVR(n) (0x1a0 + (n * 4))
|
||||
#define ETM_CIDCVR(n) (0x1b0 + (n * 4))
|
||||
#define ETM_CIDCMR 0x1bc
|
||||
#define ETM_IMPSPEC0 0x1c0
|
||||
#define ETM_IMPSPEC1 0x1c4
|
||||
#define ETM_IMPSPEC2 0x1c8
|
||||
#define ETM_IMPSPEC3 0x1cc
|
||||
#define ETM_IMPSPEC4 0x1d0
|
||||
#define ETM_IMPSPEC5 0x1d4
|
||||
#define ETM_IMPSPEC6 0x1d8
|
||||
#define ETM_IMPSPEC7 0x1dc
|
||||
#define ETM_SYNCFR 0x1e0
|
||||
#define ETM_IDR 0x1e4
|
||||
#define ETM_CCER 0x1e8
|
||||
#define ETM_EXTINSELR 0x1ec
|
||||
#define ETM_TESSEICR 0x1f0
|
||||
#define ETM_EIBCR 0x1f4
|
||||
#define ETM_TSEVR 0x1f8
|
||||
#define ETM_AUXCR 0x1fc
|
||||
#define ETM_TRACEIDR 0x200
|
||||
#define ETM_VMIDCVR 0x240
|
||||
|
||||
/* Management registers (0x300-0x314) */
|
||||
|
||||
#define ETM_OSLAR 0x300
|
||||
#define ETM_OSLSR 0x304
|
||||
#define ETM_OSSRR 0x308
|
||||
#define ETM_PDCR 0x310
|
||||
#define ETM_PDSR 0x314
|
||||
|
||||
/* Register definition */
|
||||
|
||||
/* ETMCR - 0x00 */
|
||||
|
||||
#define ETM_CR_PWD_DWN BIT(0)
|
||||
#define ETM_CR_STALL_MODE BIT(7)
|
||||
#define ETM_CR_BRANCH_BROADCAST BIT(8)
|
||||
#define ETM_CR_ETM_PRG BIT(10)
|
||||
#define ETM_CR_ETM_EN BIT(11)
|
||||
#define ETM_CR_CYC_ACC BIT(12)
|
||||
#define ETM_CR_CTXID_SIZE (BIT(14) | BIT(15))
|
||||
#define ETM_CR_TIMESTAMP_EN BIT(28)
|
||||
|
||||
/* ETM_CR_RETURN_STACK is supported by PTM, ETM not support it */
|
||||
|
||||
#define ETM_CR_RETURN_STACK BIT(29)
|
||||
|
||||
/* ETMCCR - 0x04 */
|
||||
|
||||
#define ETM_CCR_FIFOFULL BIT(23)
|
||||
|
||||
/* ETMPDCR - 0x310 */
|
||||
|
||||
#define ETM_PDCR_PWD_UP BIT(3)
|
||||
|
||||
/* ETMTECR1 - 0x024 */
|
||||
|
||||
#define ETM_TECR1_ADDR_COMP_1 BIT(0)
|
||||
#define ETM_TECR1_INC_EXC BIT(24)
|
||||
#define ETM_TECR1_START_STOP BIT(25)
|
||||
|
||||
/* ETMCCER - 0x1E8 */
|
||||
|
||||
#define ETM_CCER_TIMESTAMP BIT(22)
|
||||
#define ETM_CCER_RETSTACK BIT(23)
|
||||
|
||||
#define ETM_MODE_EXCLUDE BIT(0)
|
||||
#define ETM_MODE_CYCACC BIT(1)
|
||||
#define ETM_MODE_STALL BIT(2)
|
||||
#define ETM_MODE_TIMESTAMP BIT(3)
|
||||
#define ETM_MODE_CTXID BIT(4)
|
||||
#define ETM_MODE_BBROAD BIT(5)
|
||||
#define ETM_MODE_RET_STACK BIT(6)
|
||||
#define ETM_MODE_EXCL_KERN BIT(30)
|
||||
#define ETM_MODE_EXCL_USER BIT(31)
|
||||
#define ETM_MODE_ALL \
|
||||
(ETM_MODE_EXCLUDE | ETM_MODE_CYCACC | ETM_MODE_STALL | \
|
||||
ETM_MODE_TIMESTAMP | ETM_MODE_CTXID | ETM_MODE_BBROAD | \
|
||||
ETM_MODE_RET_STACK | ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER)
|
||||
|
||||
#define ETM_SQR_MASK 0x3
|
||||
#define ETM_TRACEID_MASK 0x3f
|
||||
#define ETM_EVENT_MASK 0x1ffff
|
||||
#define ETM_SYNC_MASK 0xfff
|
||||
#define ETM_ALL_MASK 0xffffffff
|
||||
|
||||
#define ETM_SR_PROGRAM BIT(1)
|
||||
#define ETM_SEQ_STATE_MAX_VAL 0x2
|
||||
#define ETM_PORT_SIZE_MASK (GENMASK(21, 21) | GENMASK(6, 4))
|
||||
|
||||
#define ETM_ARCH_V3_3 0x23
|
||||
#define ETM_ARCH_V3_5 0x25
|
||||
#define PFT_ARCH_V1_0 0x30
|
||||
#define PFT_ARCH_V1_1 0x31
|
||||
|
||||
/* Hard wired, always true */
|
||||
|
||||
#define ETM_HARD_WIRE_RES_A ((0x0f << 0) | (0x06 << 4))
|
||||
|
||||
/* Single addr comparator 1 */
|
||||
|
||||
#define ETM_ADD_COMP_0 ((0x00 << 7) | (0x00 << 11))
|
||||
|
||||
/* NOT(A) */
|
||||
|
||||
#define ETM_EVENT_NOT_A BIT(14)
|
||||
|
||||
#define ETM_DEFAULT_EVENT_VAL \
|
||||
(ETM_HARD_WIRE_RES_A | ETM_ADD_COMP_0 | ETM_EVENT_NOT_A)
|
||||
|
||||
#define ETM3X_SUPPORTED_OPTIONS \
|
||||
(ETM_CR_CYC_ACC | ETM_CR_TIMESTAMP_EN | ETM_CR_RETURN_STACK)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int etm_enable(FAR struct coresight_dev_s *csdev);
|
||||
static void etm_disable(FAR struct coresight_dev_s *csdev);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct coresight_source_ops_s g_etm_source_ops =
|
||||
{
|
||||
.enable = etm_enable,
|
||||
.disable = etm_disable,
|
||||
};
|
||||
|
||||
static const struct coresight_ops_s g_etm_ops =
|
||||
{
|
||||
.source_ops = &g_etm_source_ops,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_CORESIGHT_ETM_USE_COPROCESSOR
|
||||
static inline void etm_write_reg(FAR struct coresight_etm_dev_s *etmdev,
|
||||
uint32_t val, uint32_t off)
|
||||
{
|
||||
coresight_put32(val, etmdev->csdev.addr + off);
|
||||
}
|
||||
|
||||
static inline uint32_t etm_read_reg(FAR struct coresight_etm_dev_s *etmdev,
|
||||
uint32_t off)
|
||||
{
|
||||
return coresight_get32(etmdev->csdev.addr + off);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_modify_reg32
|
||||
*
|
||||
* Description:
|
||||
* Set a bitmask of register to specific value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void etm_modify_reg32(FAR struct coresight_etm_dev_s *etmdev,
|
||||
uint32_t val, uint32_t mask, uint32_t off)
|
||||
{
|
||||
uint32_t temp = etm_read_reg(etmdev, off);
|
||||
|
||||
etm_write_reg(etmdev, (temp & ~mask) | (val & mask), off);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_os_unlock
|
||||
*
|
||||
* Description:
|
||||
* When the ETM trace registers are locked, any attempt to access the
|
||||
* locked registers returns a slave-generated error response.In ETMv3.5,
|
||||
* the OS Lock is always set from an ETM reset. ARM recommends that, after
|
||||
* programming the ETM registers, you always execute an ISB instruction to
|
||||
* ensure that all updates are committed to the ETM before you restart
|
||||
* normal code execution.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void etm_os_unlock(FAR struct coresight_etm_dev_s *etmdev)
|
||||
{
|
||||
etm_write_reg(etmdev, 0x0, ETM_OSLAR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_clr_pwrdwn
|
||||
*
|
||||
* Description:
|
||||
* When pwrdown bit is set to 1, the ETM must be powered down and disabled,
|
||||
* and then operated in a low power mode with all clocks stopped. When this
|
||||
* bit is set to 1, writes to some registers and fields might be ignored.
|
||||
* ARM recommends that you use a read-modify-write procedure when modifying
|
||||
* the ETMCR.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void etm_clr_pwrdwn(FAR struct coresight_etm_dev_s *etmdev)
|
||||
{
|
||||
etm_modify_reg32(etmdev, 0, ETM_CR_PWD_DWN, ETM_CR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_set_pwrdwn
|
||||
****************************************************************************/
|
||||
|
||||
static void etm_set_pwrdwn(FAR struct coresight_etm_dev_s *etmdev)
|
||||
{
|
||||
etm_modify_reg32(etmdev, ETM_CR_PWD_DWN, ETM_CR_PWD_DWN, ETM_CR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_set_pwrup
|
||||
*
|
||||
* Description:
|
||||
* Power is provided to the ETM trace registers. This register can only be
|
||||
* accessed using a memory-mapped interface or from an external debugger.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void etm_set_pwrup(FAR struct coresight_etm_dev_s *etmdev)
|
||||
{
|
||||
coresight_modify32(ETM_PDCR_PWD_UP, ETM_PDCR_PWD_UP,
|
||||
etmdev->csdev.addr + ETM_PDCR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_clr_pwrup
|
||||
****************************************************************************/
|
||||
|
||||
static void etm_clr_pwrup(FAR struct coresight_etm_dev_s *etmdev)
|
||||
{
|
||||
coresight_modify32(0, ETM_PDCR_PWD_UP, etmdev->csdev.addr + ETM_PDCR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_timeout
|
||||
*
|
||||
* Description:
|
||||
* Loop until a bitmask of register has changed to a specific value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int etm_timeout(FAR struct coresight_etm_dev_s *etmdev,
|
||||
uint32_t val, uint32_t mask, uint32_t off)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = CONFIG_CORESIGHT_TIMEOUT; i > 0; i--)
|
||||
{
|
||||
uint32_t value = etm_read_reg(etmdev, off);
|
||||
if ((value & mask) == val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
up_udelay(1);
|
||||
}
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_set_program
|
||||
*
|
||||
* Description:
|
||||
* Set ETM Programming bit to disable all operations during programming.
|
||||
* When programming the ETM registers you must enable all the changes at
|
||||
* the same time.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void etm_set_program(FAR struct coresight_etm_dev_s *etmdev)
|
||||
{
|
||||
etm_modify_reg32(etmdev, ETM_CR_ETM_PRG, ETM_CR_ETM_PRG, ETM_CR);
|
||||
|
||||
if (etm_timeout(etmdev, ETM_SR_PROGRAM, ETM_SR_PROGRAM, ETM_SR) < 0)
|
||||
{
|
||||
cserr("timeout observed at setting ETM_SR_PROGRAM\n");
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_clr_program
|
||||
****************************************************************************/
|
||||
|
||||
static void etm_clr_program(FAR struct coresight_etm_dev_s *etmdev)
|
||||
{
|
||||
etm_modify_reg32(etmdev, 0, ETM_CR_ETM_PRG, ETM_CR);
|
||||
|
||||
if (etm_timeout(etmdev, 0, ETM_SR_PROGRAM, ETM_SR) < 0)
|
||||
{
|
||||
cserr("timeout observed at clearing ETM_SR_PROGRAM\n");
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_init_arch_data
|
||||
*
|
||||
* Description:
|
||||
* Get capabilities of current ETM architecture version.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void etm_init_arch_data(FAR struct coresight_etm_dev_s *etmdev)
|
||||
{
|
||||
uint32_t etmccr;
|
||||
|
||||
coresight_unlock(etmdev->csdev.addr);
|
||||
etm_os_unlock(etmdev);
|
||||
etm_clr_pwrdwn(etmdev);
|
||||
etm_set_pwrup(etmdev);
|
||||
etm_set_program(etmdev);
|
||||
|
||||
etmdev->arch = BMVAL(etm_read_reg(etmdev, ETM_IDR), 4, 11);
|
||||
etmdev->port_size = etm_read_reg(etmdev, ETM_CR) & ETM_PORT_SIZE_MASK;
|
||||
|
||||
etmccr = etm_read_reg(etmdev, ETM_CCR);
|
||||
etmdev->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
|
||||
etmdev->nr_cntr = BMVAL(etmccr, 13, 15);
|
||||
etmdev->nr_ext_inp = BMVAL(etmccr, 17, 19);
|
||||
etmdev->nr_ext_out = BMVAL(etmccr, 20, 22);
|
||||
etmdev->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
|
||||
|
||||
etm_clr_program(etmdev);
|
||||
etm_clr_pwrup(etmdev);
|
||||
etm_set_pwrdwn(etmdev);
|
||||
coresight_lock(etmdev->csdev.addr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_arch_supported
|
||||
*
|
||||
* Description:
|
||||
* If ETM/PTM implement is supported by current driver.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool etm_arch_supported(uint8_t arch)
|
||||
{
|
||||
switch (arch)
|
||||
{
|
||||
case ETM_ARCH_V3_3:
|
||||
case ETM_ARCH_V3_5:
|
||||
case PFT_ARCH_V1_0:
|
||||
case PFT_ARCH_V1_1:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_set_default
|
||||
*
|
||||
* Description:
|
||||
* Setup default ETM config.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void etm_set_default(struct etm_config_s *config)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Trace all memory, set according to spec */
|
||||
|
||||
config->enable_ctrl1 = BIT(24);
|
||||
config->enable_ctrl2 = 0x0;
|
||||
config->enable_event = ETM_HARD_WIRE_RES_A;
|
||||
|
||||
/* Disable all other event */
|
||||
|
||||
config->trigger_event = ETM_DEFAULT_EVENT_VAL;
|
||||
config->seq_12_event = ETM_DEFAULT_EVENT_VAL;
|
||||
config->seq_21_event = ETM_DEFAULT_EVENT_VAL;
|
||||
config->seq_23_event = ETM_DEFAULT_EVENT_VAL;
|
||||
config->seq_31_event = ETM_DEFAULT_EVENT_VAL;
|
||||
config->seq_32_event = ETM_DEFAULT_EVENT_VAL;
|
||||
config->seq_13_event = ETM_DEFAULT_EVENT_VAL;
|
||||
config->timestamp_event = ETM_DEFAULT_EVENT_VAL;
|
||||
|
||||
for (i = 0; i < ETM_MAX_CNTR; i++)
|
||||
{
|
||||
config->cntr_event[i] = ETM_DEFAULT_EVENT_VAL;
|
||||
config->cntr_rld_event[i] = ETM_DEFAULT_EVENT_VAL;
|
||||
}
|
||||
|
||||
config->sync_freq = 0x400;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_hw_enable
|
||||
****************************************************************************/
|
||||
|
||||
static int etm_hw_enable(FAR struct coresight_etm_dev_s *etmdev)
|
||||
{
|
||||
FAR struct etm_config_s *config = &etmdev->cfg;
|
||||
uint32_t etmcr;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = coresight_claim_device(etmdev->csdev.addr);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
coresight_unlock(etmdev->csdev.addr);
|
||||
etm_os_unlock(etmdev);
|
||||
etm_set_pwrup(etmdev);
|
||||
etm_clr_pwrdwn(etmdev);
|
||||
etm_set_program(etmdev);
|
||||
|
||||
etmcr = etm_read_reg(etmdev, ETM_CR);
|
||||
etmcr &= ~ETM3X_SUPPORTED_OPTIONS;
|
||||
etmcr |= ETM_CR_ETM_EN;
|
||||
etm_write_reg(etmdev, config->ctrl | etmcr, ETM_CR);
|
||||
etm_write_reg(etmdev, config->trigger_event, ETM_TRIGGER);
|
||||
etm_write_reg(etmdev, config->startstop_ctrl, ETM_TSSCR);
|
||||
etm_write_reg(etmdev, config->enable_event, ETM_TEEVR);
|
||||
etm_write_reg(etmdev, config->enable_ctrl1, ETM_TECR1);
|
||||
etm_write_reg(etmdev, config->fifofull_level, ETM_FFLR);
|
||||
for (i = 0; i < etmdev->nr_addr_cmp; i++)
|
||||
{
|
||||
etm_write_reg(etmdev, config->addr_val[i], ETM_ACVR(i));
|
||||
etm_write_reg(etmdev, config->addr_acctype[i], ETM_ACTR(i));
|
||||
}
|
||||
|
||||
for (i = 0; i < etmdev->nr_cntr; i++)
|
||||
{
|
||||
etm_write_reg(etmdev, config->cntr_rld_val[i], ETM_CNTRLDVR(i));
|
||||
etm_write_reg(etmdev, config->cntr_event[i], ETM_CNTENR(i));
|
||||
etm_write_reg(etmdev, config->cntr_rld_event[i], ETM_CNTRLDEVR(i));
|
||||
etm_write_reg(etmdev, config->cntr_val[i], ETM_CNTVR(i));
|
||||
}
|
||||
|
||||
etm_write_reg(etmdev, config->seq_12_event, ETM_SQ12EVR);
|
||||
etm_write_reg(etmdev, config->seq_21_event, ETM_SQ21EVR);
|
||||
etm_write_reg(etmdev, config->seq_23_event, ETM_SQ23EVR);
|
||||
etm_write_reg(etmdev, config->seq_31_event, ETM_SQ31EVR);
|
||||
etm_write_reg(etmdev, config->seq_32_event, ETM_SQ32EVR);
|
||||
etm_write_reg(etmdev, config->seq_13_event, ETM_SQ13EVR);
|
||||
etm_write_reg(etmdev, config->seq_curr_state, ETM_SQR);
|
||||
for (i = 0; i < etmdev->nr_ext_out; i++)
|
||||
{
|
||||
etm_write_reg(etmdev, ETM_DEFAULT_EVENT_VAL, ETM_EXTOUTEVR(i));
|
||||
}
|
||||
|
||||
for (i = 0; i < etmdev->nr_ctxid_cmp; i++)
|
||||
{
|
||||
etm_write_reg(etmdev, config->ctxid_pid[i], ETM_CIDCVR(i));
|
||||
}
|
||||
|
||||
etm_write_reg(etmdev, config->ctxid_mask, ETM_CIDCMR);
|
||||
etm_write_reg(etmdev, config->sync_freq, ETM_SYNCFR);
|
||||
|
||||
/* No external input selected */
|
||||
|
||||
etm_write_reg(etmdev, 0x0, ETM_EXTINSELR);
|
||||
etm_write_reg(etmdev, config->timestamp_event, ETM_TSEVR);
|
||||
|
||||
/* No auxiliary control selected */
|
||||
|
||||
etm_write_reg(etmdev, 0x0, ETM_AUXCR);
|
||||
|
||||
etm_write_reg(etmdev, etmdev->traceid, ETM_TRACEIDR);
|
||||
|
||||
/* No VMID comparator value selected */
|
||||
|
||||
etm_write_reg(etmdev, 0x0, ETM_VMIDCVR);
|
||||
|
||||
etm_clr_program(etmdev);
|
||||
coresight_lock(etmdev->csdev.addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_hw_disable
|
||||
****************************************************************************/
|
||||
|
||||
static void etm_hw_disable(FAR struct coresight_etm_dev_s *etmdev)
|
||||
{
|
||||
FAR struct etm_config_s *config = &etmdev->cfg;
|
||||
int i;
|
||||
|
||||
coresight_unlock(etmdev->csdev.addr);
|
||||
etm_set_program(etmdev);
|
||||
|
||||
/* Read back sequencer and counters for post trace analysis */
|
||||
|
||||
config->seq_curr_state = etm_read_reg(etmdev, ETM_SQR) & ETM_SQR_MASK;
|
||||
for (i = 0; i < etmdev->nr_cntr; i++)
|
||||
{
|
||||
config->cntr_val[i] = etm_read_reg(etmdev, ETM_CNTVR(i));
|
||||
}
|
||||
|
||||
etm_set_pwrdwn(etmdev);
|
||||
coresight_lock(etmdev->csdev.addr);
|
||||
|
||||
coresight_disclaim_device(etmdev->csdev.addr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_enable
|
||||
****************************************************************************/
|
||||
|
||||
static int etm_enable(FAR struct coresight_dev_s *csdev)
|
||||
{
|
||||
FAR struct coresight_etm_dev_s *etmdev =
|
||||
(FAR struct coresight_etm_dev_s *)csdev;
|
||||
int ret = 0;
|
||||
|
||||
if (etmdev->refcnt++ == 0)
|
||||
{
|
||||
ret = etm_hw_enable(etmdev);
|
||||
if (ret < 0)
|
||||
{
|
||||
etmdev->refcnt--;
|
||||
cserr("%s enabled\n", csdev->name);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_enable
|
||||
****************************************************************************/
|
||||
|
||||
static void etm_disable(FAR struct coresight_dev_s *csdev)
|
||||
{
|
||||
FAR struct coresight_etm_dev_s *etmdev =
|
||||
(FAR struct coresight_etm_dev_s *)csdev;
|
||||
|
||||
if (--etmdev->refcnt == 0)
|
||||
{
|
||||
etm_hw_disable(etmdev);
|
||||
csinfo("etm %s disabled\n", csdev->name);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_config
|
||||
*
|
||||
* Description:
|
||||
* Configure the etm device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* etmdev - Pointer to the ETM device to config.
|
||||
* config - Configuration need to be set to ETM device.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negative value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int etm_config(FAR struct coresight_etm_dev_s *etmdev,
|
||||
FAR const struct etm_config_s *config)
|
||||
{
|
||||
coresight_unlock(etmdev->csdev.addr);
|
||||
etm_os_unlock(etmdev);
|
||||
etm_clr_pwrdwn(etmdev);
|
||||
etm_set_pwrup(etmdev);
|
||||
etm_set_program(etmdev);
|
||||
|
||||
memcpy(&etmdev->cfg, config, sizeof(struct etm_config_s));
|
||||
|
||||
if ((etmdev->cfg.ctrl & ETM_CR_RETURN_STACK) &&
|
||||
!(etm_read_reg(etmdev, ETM_CCER) & ETM_CCER_RETSTACK))
|
||||
{
|
||||
etmdev->cfg.ctrl &= ~ETM_CR_RETURN_STACK;
|
||||
}
|
||||
|
||||
etm_clr_program(etmdev);
|
||||
etm_clr_pwrup(etmdev);
|
||||
etm_set_pwrdwn(etmdev);
|
||||
coresight_lock(etmdev->csdev.addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_register
|
||||
*
|
||||
* Description:
|
||||
* Register an ETM/PTM devices.
|
||||
*
|
||||
* Input Parameters:
|
||||
* desc - A description of this coresight device.
|
||||
*
|
||||
* Returned Value:
|
||||
* Pointer to an ETM device on success; NULL on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct coresight_etm_dev_s *
|
||||
etm_register(FAR const struct coresight_desc_s *desc)
|
||||
{
|
||||
FAR struct coresight_etm_dev_s *etmdev;
|
||||
FAR struct coresight_dev_s *csdev;
|
||||
int ret;
|
||||
|
||||
etmdev = kmm_zalloc(sizeof(struct coresight_etm_dev_s));
|
||||
if (etmdev == NULL)
|
||||
{
|
||||
cserr("%s:malloc failed!\n", desc->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
etmdev->cpu = desc->cpu;
|
||||
etmdev->csdev.addr = desc->addr;
|
||||
|
||||
etm_init_arch_data(etmdev);
|
||||
|
||||
if (!etm_arch_supported(etmdev->arch))
|
||||
{
|
||||
kmm_free(etmdev);
|
||||
cserr("%s:current implement version is not supported\n", desc->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
etmdev->traceid = coresight_get_cpu_trace_id(etmdev->cpu);
|
||||
etm_set_default(&etmdev->cfg);
|
||||
|
||||
csdev = &etmdev->csdev;
|
||||
csdev->ops = &g_etm_ops;
|
||||
ret = coresight_register(csdev, desc);
|
||||
if (ret < 0)
|
||||
{
|
||||
kmm_free(etmdev);
|
||||
cserr("%s:register failed\n", desc->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return etmdev;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_unregister
|
||||
*
|
||||
* Description:
|
||||
* Unregister an EMT/PTM device.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void etm_unregister(FAR struct coresight_etm_dev_s *etmdev)
|
||||
{
|
||||
coresight_unregister(&etmdev->csdev);
|
||||
kmm_free(etmdev);
|
||||
}
|
@ -150,8 +150,8 @@ static void stm_hw_disable(FAR struct coresight_stm_dev_s *stmdev)
|
||||
coresight_put32(0x0, stmdev->csdev.addr + STM_HEER);
|
||||
coresight_put32(0x0, stmdev->csdev.addr + STM_HETER);
|
||||
|
||||
if (coresight_timeout(stmdev->csdev.addr, STM_TCSR,
|
||||
STM_TCSR_BUSY, 0) < 0)
|
||||
if (coresight_timeout(0x0, STM_TCSR_BUSY,
|
||||
stmdev->csdev.addr + STM_TCSR) < 0)
|
||||
{
|
||||
cserr("timeout waiting for STM stopped\n");
|
||||
}
|
||||
|
@ -107,25 +107,22 @@ static int tpiu_hw_enable(FAR struct coresight_tpiu_dev_s *tpiudev)
|
||||
|
||||
static void tpiu_hw_disable(FAR struct coresight_tpiu_dev_s *tpiudev)
|
||||
{
|
||||
uint32_t ffcr;
|
||||
|
||||
coresight_unlock(tpiudev->csdev.addr);
|
||||
|
||||
/* Trigger a formatter stop event. */
|
||||
|
||||
ffcr = coresight_get32(tpiudev->csdev.addr + TPIU_FFCR);
|
||||
ffcr |= TPIU_FFCR_STOP_FI;
|
||||
coresight_put32(ffcr, tpiudev->csdev.addr + TPIU_FFCR);
|
||||
ffcr |= TPIU_FFCR_FON_MAN;
|
||||
coresight_put32(ffcr, tpiudev->csdev.addr + TPIU_FFCR);
|
||||
if (coresight_timeout(tpiudev->csdev.addr, TPIU_FFCR,
|
||||
TPIU_FFCR_FON_MAN, 0) < 0)
|
||||
coresight_modify32(TPIU_FFCR_STOP_FI, TPIU_FFCR_STOP_FI,
|
||||
tpiudev->csdev.addr + TPIU_FFCR);
|
||||
coresight_modify32(TPIU_FFCR_FON_MAN, TPIU_FFCR_FON_MAN,
|
||||
tpiudev->csdev.addr + TPIU_FFCR);
|
||||
if (coresight_timeout(0, TPIU_FFCR_FON_MAN,
|
||||
tpiudev->csdev.addr + TPIU_FFCR) < 0)
|
||||
{
|
||||
cserr("timeout while waiting for completion of Manual Flush\n");
|
||||
}
|
||||
|
||||
if (coresight_timeout(tpiudev->csdev.addr, TPIU_FFSR,
|
||||
TPIU_FFSR_FT_STOPPED, TPIU_FFSR_FT_STOPPED) < 0)
|
||||
if (coresight_timeout(TPIU_FFSR_FT_STOPPED, TPIU_FFSR_FT_STOPPED,
|
||||
tpiudev->csdev.addr + TPIU_FFSR) < 0)
|
||||
{
|
||||
cserr("timeout while waiting for Formatter to Stop\n");
|
||||
}
|
||||
|
@ -122,6 +122,10 @@ struct coresight_desc_s
|
||||
enum coresight_dev_type_e type;
|
||||
union coresight_dev_subtype_u subtype;
|
||||
|
||||
/* Used in ETM device. */
|
||||
|
||||
uint8_t cpu;
|
||||
|
||||
/* Used in funnel devices. */
|
||||
|
||||
int inport_num;
|
||||
|
139
include/nuttx/coresight/coresight_etm.h
Normal file
139
include/nuttx/coresight/coresight_etm.h
Normal file
@ -0,0 +1,139 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/coresight/coresight_etm.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_CORESIGHT_CORESIGHT_ETM_H
|
||||
#define __INCLUDE_NUTTX_CORESIGHT_CORESIGHT_ETM_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/coresight/coresight.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define ETM_MAX_ADDR_CMP 16
|
||||
#define ETM_MAX_CNTR 4
|
||||
#define ETM_MAX_CTXID_CMP 3
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct etm_config_s
|
||||
{
|
||||
uint32_t ctrl; /* ETMCR */
|
||||
uint32_t trigger_event; /* ETMTRIGGER */
|
||||
uint32_t startstop_ctrl; /* ETMTSSCR */
|
||||
uint32_t enable_event; /* ETMTEEVR */
|
||||
uint32_t enable_ctrl1; /* ETMTECR1 */
|
||||
uint32_t enable_ctrl2; /* ETMTECR2 */
|
||||
uint32_t fifofull_level; /* ETMFFLR */
|
||||
uint8_t addr_idx; /* Index for the address comparator selection. */
|
||||
uint32_t addr_val[ETM_MAX_ADDR_CMP]; /* Value for address comparator register. */
|
||||
uint32_t addr_acctype[ETM_MAX_ADDR_CMP]; /* Access type for address comparator register. */
|
||||
uint32_t addr_type[ETM_MAX_ADDR_CMP]; /* Current status of the comparator register. */
|
||||
uint8_t cntr_idx; /* Index for the counter register selection */
|
||||
uint32_t cntr_rld_val[ETM_MAX_CNTR]; /* Reload value of a counter register. */
|
||||
uint32_t cntr_event[ETM_MAX_CNTR]; /* Control for counter enable register. */
|
||||
uint32_t cntr_rld_event[ETM_MAX_CNTR]; /* Value for counter reload event register. */
|
||||
uint32_t cntr_val[ETM_MAX_CNTR]; /* Counter value register. */
|
||||
uint32_t seq_12_event; /* Event causing the transition from 1 to 2 */
|
||||
uint32_t seq_21_event; /* Event causing the transition from 2 to 1 */
|
||||
uint32_t seq_23_event; /* Event causing the transition from 2 to 3 */
|
||||
uint32_t seq_31_event; /* Event causing the transition from 3 to 1 */
|
||||
uint32_t seq_32_event; /* Event causing the transition from 3 to 2 */
|
||||
uint32_t seq_13_event; /* Event causing the transition from 1 to 3 */
|
||||
uint32_t seq_curr_state; /* Current value of the sequencer register. */
|
||||
uint8_t ctxid_idx; /* Index for the context ID registers. */
|
||||
uint32_t ctxid_pid[ETM_MAX_CTXID_CMP]; /* Value for the context ID to trigger on */
|
||||
uint32_t ctxid_mask; /* Mask applicable to all the context IDs. */
|
||||
uint32_t sync_freq; /* Synchronisation frequency. */
|
||||
uint32_t timestamp_event; /* ETMTSEVR */
|
||||
};
|
||||
|
||||
struct coresight_etm_dev_s
|
||||
{
|
||||
struct coresight_dev_s csdev;
|
||||
struct etm_config_s cfg;
|
||||
uint8_t refcnt;
|
||||
int cpu; /* The cpu this component is affined to */
|
||||
int port_size; /* Out port size */
|
||||
int traceid; /* Trace id */
|
||||
uint8_t arch; /* ETM/PTM version number */
|
||||
uint8_t nr_addr_cmp; /* Number of pairs of address comparators */
|
||||
uint8_t nr_cntr; /* Number of counters */
|
||||
uint8_t nr_ext_inp; /* Number of external input */
|
||||
uint8_t nr_ext_out; /* Number of external output */
|
||||
uint8_t nr_ctxid_cmp; /* Number of contextID comparators */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_register
|
||||
*
|
||||
* Description:
|
||||
* Register an ETM/PTM devices.
|
||||
*
|
||||
* Input Parameters:
|
||||
* desc - A description of this coresight device.
|
||||
*
|
||||
* Returned Value:
|
||||
* Pointer to an ETM device on success; NULL on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct coresight_etm_dev_s *
|
||||
etm_register(FAR const struct coresight_desc_s *desc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_unregister
|
||||
*
|
||||
* Description:
|
||||
* Unregister an EMT/PTM device.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void etm_unregister(FAR struct coresight_etm_dev_s *etmdev);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: etm_config
|
||||
*
|
||||
* Description:
|
||||
* Configure the etm device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* etmdev - Pointer to the ETM device to config.
|
||||
* config - Configuration need to be set to ETM device.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negative value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int etm_config(FAR struct coresight_etm_dev_s *etmdev,
|
||||
FAR const struct etm_config_s *config);
|
||||
|
||||
#endif //__INCLUDE_NUTTX_CORESIGHT_CORESIGHT_ETM_H
|
Loading…
Reference in New Issue
Block a user