diff --git a/drivers/coresight/CMakeLists.txt b/drivers/coresight/CMakeLists.txt index 29bda14e2d9..5885df1aef2 100644 --- a/drivers/coresight/CMakeLists.txt +++ b/drivers/coresight/CMakeLists.txt @@ -41,6 +41,11 @@ if(CONFIG_CORESIGHT) list(APPEND SRCS coresight_stm.c) endif() + if(CONFIG_CORESIGHT_TMC) + list(APPEND SRCS coresight_tmc_core.c coresight_tmc_etf.c + coresight_tmc_etr.c) + endif() + if(CONFIG_CORESIGHT_TPIU) list(APPEND SRCS coresight_tpiu.c) endif() diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig index 3ea611a806a..71fa025bc10 100644 --- a/drivers/coresight/Kconfig +++ b/drivers/coresight/Kconfig @@ -51,6 +51,10 @@ config CORESIGHT_STM bool "STM coresight device support" default n +config CORESIGHT_TMC + bool "TMC coresight device support" + default n + config CORESIGHT_TPIU bool "TPIU coresight device support" default n diff --git a/drivers/coresight/Make.defs b/drivers/coresight/Make.defs index b3852b0c570..b2219e53db6 100644 --- a/drivers/coresight/Make.defs +++ b/drivers/coresight/Make.defs @@ -44,6 +44,10 @@ ifeq ($(CONFIG_CORESIGHT_STM),y) CSRCS += coresight_stm.c endif +ifeq ($(CONFIG_CORESIGHT_TMC),y) +CSRCS += coresight_tmc_core.c coresight_tmc_etf.c coresight_tmc_etr.c +endif + ifeq ($(CONFIG_CORESIGHT_TPIU),y) CSRCS += coresight_tpiu.c endif diff --git a/drivers/coresight/coresight_tmc_core.c b/drivers/coresight/coresight_tmc_core.c new file mode 100644 index 00000000000..da5d4fb25c4 --- /dev/null +++ b/drivers/coresight/coresight_tmc_core.c @@ -0,0 +1,204 @@ +/**************************************************************************** + * drivers/coresight/coresight_tmc_core.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 +#include +#include +#include + +#include + +#include "coresight_common.h" +#include "coresight_tmc_core.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tmc_etf_get_memwidth + ****************************************************************************/ + +static enum tmc_mem_intf_width_e tmc_etf_get_memwidth(uint32_t devid) +{ + /* Indicate the minimum alignemnt for RRR/RURP/RWP/DBA etc registers. */ + + switch (BMVAL(devid, 8, 10)) + { + case 0x2: + return TMC_MEM_INTF_WIDTH_32BITS; + case 0x3: + return TMC_MEM_INTF_WIDTH_64BITS; + case 0x4: + return TMC_MEM_INTF_WIDTH_128BITS; + case 0x5: + return TMC_MEM_INTF_WIDTH_256BITS; + default: + return 0; + } +} + +/**************************************************************************** + * Name: tmc_etr_get_memwidth + ****************************************************************************/ + +static enum tmc_mem_intf_width_e tmc_etr_get_memwidth(uint32_t devid) +{ + uint32_t val = (BMVAL(devid, 14, 15) << 3) | BMVAL(devid, 8, 10); + + /* Indicate the minimum alignemnt for RRR/RURP/RWP/DBA etc registers. */ + + switch (val) + { + case 0x5: + return TMC_MEM_INTF_WIDTH_32BITS; + case 0x6: + return TMC_MEM_INTF_WIDTH_64BITS; + case 0x7: + return TMC_MEM_INTF_WIDTH_128BITS; + case 0x8: + return TMC_MEM_INTF_WIDTH_256BITS; + default: + return 0; + } +} + +/**************************************************************************** + * Name: tmc_init_arch_data + ****************************************************************************/ + +static void tmc_init_arch_data(FAR struct coresight_tmc_dev_s *tmcdev, + FAR const struct coresight_desc_s *desc) +{ + uint32_t devid; + + coresight_unlock(desc->addr); + devid = coresight_get32(desc->addr + CORESIGHT_DEVID); + tmcdev->config_type = BMVAL(devid, 6, 7); + if (tmcdev->config_type == TMC_CONFIG_TYPE_ETR) + { + tmcdev->size = desc->buffer_size; + tmcdev->burst_size = desc->burst_size; + tmcdev->mmwidth = tmc_etr_get_memwidth(devid); + } + else + { + tmcdev->size = coresight_get32(desc->addr + TMC_RSZ) * 4; + tmcdev->mmwidth = tmc_etf_get_memwidth(devid); + } + + coresight_lock(desc->addr); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tmc_register + * + * Description: + * Register a TMC devices. + * + * Input Parameters: + * desc - A description of this coresight device. + * + * Returned Value: + * Pointer to a TMC device on success; NULL on failure. + * + ****************************************************************************/ + +FAR struct coresight_tmc_dev_s * +tmc_register(FAR const struct coresight_desc_s *desc) +{ + FAR struct coresight_tmc_dev_s *tmcdev; + int ret = -EINVAL; + + tmcdev = kmm_zalloc(sizeof(struct coresight_tmc_dev_s)); + if (tmcdev == NULL) + { + cserr("%s:malloc failed!\n", desc->name); + return NULL; + } + + tmc_init_arch_data(tmcdev, desc); + + switch (tmcdev->config_type) + { + case TMC_CONFIG_TYPE_ETB: + case TMC_CONFIG_TYPE_ETF: + ret = tmc_etf_register(tmcdev, desc); + break; + + case TMC_CONFIG_TYPE_ETR: + ret = tmc_etr_register(tmcdev, desc); + break; + + default: + cserr("config type error\n"); + break; + } + + if (ret < 0) + { + kmm_free(tmcdev); + return NULL; + } + + nxmutex_init(&tmcdev->lock); + return tmcdev; +} + +/**************************************************************************** + * Name: tmc_unregister + * + * Description: + * Unregister a TMC devices. + * + * Input Parameters: + * tmcdev - Pointer to the TMC device. + * + ****************************************************************************/ + +void tmc_unregister(FAR struct coresight_tmc_dev_s *tmcdev) +{ + switch (tmcdev->config_type) + { + case TMC_CONFIG_TYPE_ETB: + case TMC_CONFIG_TYPE_ETF: + tmc_etf_unregister(tmcdev); + break; + + case TMC_CONFIG_TYPE_ETR: + tmc_etr_unregister(tmcdev); + break; + + default: + cserr("wrong config type\n"); + break; + } + + nxmutex_destroy(&tmcdev->lock); + kmm_free(tmcdev); +} diff --git a/drivers/coresight/coresight_tmc_core.h b/drivers/coresight/coresight_tmc_core.h new file mode 100644 index 00000000000..7de33133b8d --- /dev/null +++ b/drivers/coresight/coresight_tmc_core.h @@ -0,0 +1,189 @@ +/**************************************************************************** + * drivers/coresight/coresight_tmc_core.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 __DRIVERS_CORESIGHT_CORESIGHT_TMC_CORE_H +#define __DRIVERS_CORESIGHT_CORESIGHT_TMC_CORE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define TMC_RSZ 0x004 +#define TMC_STS 0x00c +#define TMC_RRD 0x010 +#define TMC_RRP 0x014 +#define TMC_RWP 0x018 +#define TMC_TRG 0x01c +#define TMC_CTL 0x020 +#define TMC_RWD 0x024 +#define TMC_MODE 0x028 +#define TMC_LBUFLEVEL 0x02c +#define TMC_CBUFLEVEL 0x030 +#define TMC_BUFWM 0x034 +#define TMC_RRPHI 0x038 +#define TMC_RWPHI 0x03c +#define TMC_AXICTL 0x110 +#define TMC_DBALO 0x118 +#define TMC_DBAHI 0x11c +#define TMC_FFSR 0x300 +#define TMC_FFCR 0x304 +#define TMC_PSCR 0x308 +#define TMC_ITMISCOP0 0xee0 +#define TMC_ITTRFLIN 0xee8 +#define TMC_ITATBDATA0 0xeec +#define TMC_ITATBCTR2 0xef0 +#define TMC_ITATBCTR1 0xef4 +#define TMC_ITATBCTR0 0xef8 +#define TMC_AUTHSTATUS 0xfb8 + +/* TMC_AUTHSTATUS - 0xfb8 */ + +#define TMC_AUTH_NSID_MASK GENMASK(1, 0) +#define TMC_NSID_EN 0x03 + +/* TMC_CTL - 0x020 */ + +#define TMC_CTL_CAPT_EN BIT(0) + +/* TMC_STS - 0x00C */ + +#define TMC_STS_FULL BIT(0) +#define TMC_STS_TRIGGERED BIT(1) +#define TMC_STS_TMCREADY BIT(2) +#define TMC_STS_MEMERR BIT(5) + +/* TMC_AXICTL - 0x110 + * + * TMC AXICTL format for SoC-400 + * Bits [0-1] : ProtCtrlBit0-1 + * Bits [2-5] : CacheCtrlBits 0-3 (AXCACHE) + * Bit 6 : Reserved + * Bit 7 : ScatterGatherMode + * Bits [8-11] : WrBurstLen + * Bits [12-31] : Reserved. + * TMC AXICTL format for SoC-600, as above except: + * Bits [2-5 : AXI WCACHE + * Bits [16-19] : AXI RCACHE + * Bits [20-31] : Reserved + */ + +#define TMC_AXICTL_CLEAR_MASK 0xfbf +#define TMC_AXICTL_ARCACHE_MASK (0xf << 16) + +#define TMC_AXICTL_PROT_CTL_B0 BIT(0) +#define TMC_AXICTL_PROT_CTL_B1 BIT(1) +#define TMC_AXICTL_SCT_GAT_MODE BIT(7) +#define TMC_AXICTL_WR_BURST(v) (((v) & 0xf) << 8) +#define TMC_AXICTL_WR_BURST_16 0xf + +/* Write-back Read and Write-allocate */ + +#define TMC_AXICTL_AXCACHE_OS (0xf << 2) +#define TMC_AXICTL_ARCACHE_OS (0xf << 16) + +/* TMC_FFCR - 0x304 */ + +#define TMC_FFCR_EN_FMT BIT(0) +#define TMC_FFCR_EN_TI BIT(1) +#define TMC_FFCR_FON_FLIN BIT(4) +#define TMC_FFCR_FON_TRIG_EVT BIT(5) +#define TMC_FFCR_FON_MAN BIT(6) +#define TMC_FFCR_TRIGON_TRIGIN BIT(8) +#define TMC_FFCR_STOP_ON_FLUSH BIT(12) + +#define TMC_DEVID_AXIAW_VALID BIT(16) +#define TMC_DEVID_NOSCAT BIT(24) +#define TMC_DEVID_AXIAW_SHIFT 17 +#define TMC_DEVID_AXIAW_MASK 0x7f + +/* TMC ETR Capability bit definitions. These need to be set by software. */ + +#define TMC_ETR_SG (0x1U << 0) + +/* ETR has separate read/write cache encodings. */ + +#define TMC_ETR_AXI_ARCACHE (0x1U << 1) + +/* TMC_ETR_SAVE_RESTORE - Values of RRP/RWP/STS.Full are + * retained when TMC leaves Disabled state, allowing us to continue + * the tracing from a point where we stopped. This also implies that + * the RRP/RWP/STS.Full should always be programmed to the correct + * value. Unfortunately this is not advertised by the hardware, + * so we have to rely on PID of the IP to detect the functionality. + */ + +#define TMC_ETR_SAVE_RESTORE (0x1U << 2) + +/* Coresight SoC-600 TMC-ETR unadvertised capabilities */ + +#define TMC_600_ETR_CAPS \ + (TMC_ETR_SAVE_RESTORE | TMC_ETR_AXI_ARCACHE) + +#define TMC_MAX_NAME_LEN 32 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +enum tmc_mode_e +{ + TMC_MODE_CIRCULAR_BUFFER, + TMC_MODE_SOFTWARE_FIFO, + TMC_MODE_HARDWARE_FIFO, +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: tmc_etf_register + ****************************************************************************/ + +int tmc_etf_register(FAR struct coresight_tmc_dev_s *tmcdev, + FAR const struct coresight_desc_s *desc); + +/**************************************************************************** + * Name: tmc_etr_register + ****************************************************************************/ + +int tmc_etr_register(FAR struct coresight_tmc_dev_s *tmcdev, + FAR const struct coresight_desc_s *desc); + +/**************************************************************************** + * Name: tmc_etf_unregister + ****************************************************************************/ + +void tmc_etf_unregister(FAR struct coresight_tmc_dev_s * tmcdev); + +/**************************************************************************** + * Name: tmc_etr_unregister + ****************************************************************************/ + +void tmc_etr_unregister(FAR struct coresight_tmc_dev_s * tmcdev); + +#endif //__DRIVERS_CORESIGHT_CORESIGHT_TMC_CORE_H diff --git a/drivers/coresight/coresight_tmc_etf.c b/drivers/coresight/coresight_tmc_etf.c new file mode 100644 index 00000000000..1a68559835c --- /dev/null +++ b/drivers/coresight/coresight_tmc_etf.c @@ -0,0 +1,570 @@ +/**************************************************************************** + * drivers/coresight/coresight_tmc_etf.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 +#include +#include +#include +#include +#include +#include + +#include + +#include "coresight_common.h" +#include "coresight_tmc_core.h" + +/**************************************************************************** + * Private Functions Prototypes + ****************************************************************************/ + +static int tmc_etf_sink_enable(FAR struct coresight_dev_s *csdev); +static void tmc_etf_sink_disable(FAR struct coresight_dev_s *csdev); +static int tmc_etf_link_enable(FAR struct coresight_dev_s *csdev, + int iport, int oport); +static void tmc_etf_link_disable(FAR struct coresight_dev_s *csdev, + int iport, int oport); + +static int tmc_etf_open(FAR struct file *filep); +static int tmc_etf_close(FAR struct file *filep); +static ssize_t tmc_etf_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* TMC-ETB and TMC-ETF sink device operations. */ + +static const struct coresight_sink_ops_s g_tmc_etf_sink_ops = +{ + .enable = tmc_etf_sink_enable, + .disable = tmc_etf_sink_disable, +}; + +static const struct coresight_ops_s g_tmc_sink_ops = +{ + .sink_ops = &g_tmc_etf_sink_ops, +}; + +/* TMC-ETF link device operations. */ + +static const struct coresight_link_ops_s g_tmc_etf_link_ops = +{ + .enable = tmc_etf_link_enable, + .disable = tmc_etf_link_disable, +}; + +static const struct coresight_ops_s g_tmc_link_ops = +{ + .link_ops = &g_tmc_etf_link_ops, +}; + +static const struct file_operations g_tmc_fops = +{ + tmc_etf_open, /* open */ + tmc_etf_close, /* close */ + tmc_etf_read, /* read */ + NULL, /* write */ + NULL, /* seek */ + NULL, /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tmc_etf_sink_hw_enable + ****************************************************************************/ + +static int tmc_etf_sink_hw_enable(FAR struct coresight_tmc_dev_s *tmcdev) +{ + coresight_unlock(tmcdev->csdev.addr); + + /* Wait for TMCSReady bit to be set. */ + + if (coresight_timeout(TMC_STS_TMCREADY, TMC_STS_TMCREADY, + tmcdev->csdev.addr + TMC_STS) < 0) + { + cserr("tmc device is not ready\n"); + coresight_lock(tmcdev->csdev.addr); + return -EAGAIN; + } + + /* TMC-ETB and TMC-ETF sink device use cirular buffer mode. */ + + coresight_put32(TMC_MODE_CIRCULAR_BUFFER, tmcdev->csdev.addr + TMC_MODE); + coresight_put32(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI | TMC_FFCR_FON_FLIN | + TMC_FFCR_FON_TRIG_EVT | TMC_FFCR_TRIGON_TRIGIN, + tmcdev->csdev.addr + TMC_FFCR); + coresight_put32(tmcdev->trigger_cntr, tmcdev->csdev.addr + TMC_TRG); + + /* Enable capture. */ + + coresight_put32(TMC_CTL_CAPT_EN, tmcdev->csdev.addr + TMC_CTL); + + coresight_lock(tmcdev->csdev.addr); + return 0; +} + +/**************************************************************************** + * Name: tmc_etf_link_hw_enable + ****************************************************************************/ + +static int tmc_etf_link_hw_enable(FAR struct coresight_tmc_dev_s *tmcdev) +{ + coresight_unlock(tmcdev->csdev.addr); + + /* Wait for TMCSReady bit to be set. */ + + if (coresight_timeout(TMC_STS_TMCREADY, TMC_STS_TMCREADY, + tmcdev->csdev.addr + TMC_STS) < 0) + { + cserr("tmc device is not ready\n"); + coresight_lock(tmcdev->csdev.addr); + return -EAGAIN; + } + + /* TMC-ETF link device use Hardware FIFO buffer mode. */ + + coresight_put32(TMC_MODE_HARDWARE_FIFO, tmcdev->csdev.addr + TMC_MODE); + coresight_put32(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI, + tmcdev->csdev.addr + TMC_FFCR); + coresight_put32(0x0, tmcdev->csdev.addr + TMC_BUFWM); + + /* Enable capture. */ + + coresight_put32(TMC_CTL_CAPT_EN, tmcdev->csdev.addr + TMC_CTL); + + coresight_lock(tmcdev->csdev.addr); + return 0; +} + +/**************************************************************************** + * Name: tmc_flush_and_stop + ****************************************************************************/ + +static void tmc_flush_and_stop(FAR struct coresight_tmc_dev_s *tmcdev) +{ + coresight_modify32(TMC_FFCR_STOP_ON_FLUSH, TMC_FFCR_STOP_ON_FLUSH, + tmcdev->csdev.addr + TMC_FFCR); + coresight_modify32(TMC_FFCR_FON_MAN, TMC_FFCR_FON_MAN, + tmcdev->csdev.addr + TMC_FFCR); + if (coresight_timeout(0x0, TMC_FFCR_FON_MAN, + tmcdev->csdev.addr + TMC_FFCR) < 0) + { + cserr("timeout while waiting for completion of Manual Flush\n"); + } + + if (coresight_timeout(TMC_STS_TMCREADY, TMC_STS_TMCREADY, + tmcdev->csdev.addr + TMC_STS) < 0) + { + cserr("timeout while waiting for TMC to be Ready\n"); + } +} + +/**************************************************************************** + * Name: tmc_etf_hw_read + * + * Description: + * Dump ETB RAM buffer to device's buffer for usrspace's read. It just need + * to performing successive reads to the RRD Register, until the value + * 0xFFFFFFFF is returned whick is kind different from coresight ETB + * device's reading process. refers to TRM. + * + ****************************************************************************/ + +static void tmc_etf_hw_read(FAR struct coresight_tmc_dev_s *tmcdev) +{ + FAR uint32_t *bufptr; + uint32_t read_data; + + bufptr = tmcdev->buf; + tmcdev->len = 0; + for (; ; ) + { + read_data = coresight_get32(tmcdev->csdev.addr + TMC_RRD); + if (read_data == 0xffffffff) + { + break; + } + + memcpy(bufptr, &read_data, 4); + bufptr += 1; + tmcdev->len += 4; + } + + if ((coresight_get32(tmcdev->csdev.addr + TMC_STS) & TMC_STS_FULL) == 1) + { + coresight_insert_barrier_packet(tmcdev->buf); + } +} + +/**************************************************************************** + * Name: tmc_etf_hw_disable_and_read + * + * Description: + * Used for ETF sink devices to dump trace buffer. Do not dump trace buffer + * in tmc_etf_hw_disable to avoid trace buffer's data confusion when a + * process is reading trace buffer and anther process calles tmc_disable. + * + ****************************************************************************/ + +static void +tmc_etf_hw_disable_and_read(FAR struct coresight_tmc_dev_s *tmcdev) +{ + coresight_unlock(tmcdev->csdev.addr); + tmc_flush_and_stop(tmcdev); + + /* This is kind different from ETB coresight device, it should read data + * from ram buffer in stopped state rather then disabled state. + */ + + tmc_etf_hw_read(tmcdev); + + /* Disable capture enable bit. */ + + coresight_put32(0x0, tmcdev->csdev.addr + TMC_CTL); + coresight_lock(tmcdev->csdev.addr); +} + +/**************************************************************************** + * Name: tmc_etf_hw_disable + * + * Description: + * ETF link devices and ETF sink devices share same disable flow. + * + ****************************************************************************/ + +static void tmc_etf_hw_disable(FAR struct coresight_tmc_dev_s *tmcdev) +{ + coresight_unlock(tmcdev->csdev.addr); + tmc_flush_and_stop(tmcdev); + + /* Disable capture enable bit. */ + + coresight_put32(0x0, tmcdev->csdev.addr + TMC_CTL); + coresight_lock(tmcdev->csdev.addr); +} + +/**************************************************************************** + * Name: tmc_etf_sink_enable + ****************************************************************************/ + +static int tmc_etf_sink_enable(FAR struct coresight_dev_s *csdev) +{ + FAR struct coresight_tmc_dev_s *tmcdev = + (FAR struct coresight_tmc_dev_s *)csdev; + int ret = 0; + + if (tmcdev->refcnt++ == 0) + { + ret = coresight_claim_device(tmcdev->csdev.addr); + if (ret < 0) + { + tmcdev->refcnt--; + cserr("%s claimed failed\n", csdev->name); + return ret; + } + + ret = tmc_etf_sink_hw_enable(tmcdev); + if (ret < 0) + { + tmcdev->refcnt--; + coresight_disclaim_device(tmcdev->csdev.addr); + cserr("%s enable failed\n", csdev->name); + } + } + + return ret; +} + +/**************************************************************************** + * Name: tmc_etf_sink_disable + ****************************************************************************/ + +static void tmc_etf_sink_disable(FAR struct coresight_dev_s *csdev) +{ + FAR struct coresight_tmc_dev_s *tmcdev = + (FAR struct coresight_tmc_dev_s *)csdev; + + if (--tmcdev->refcnt == 0) + { + tmc_etf_hw_disable(tmcdev); + coresight_disclaim_device(tmcdev->csdev.addr); + csinfo("%s disabled\n", csdev->name); + } +} + +/**************************************************************************** + * Name: tmc_etf_link_enable + ****************************************************************************/ + +static int tmc_etf_link_enable(FAR struct coresight_dev_s *csdev, + int iport, int oport) +{ + FAR struct coresight_tmc_dev_s *tmcdev = + (FAR struct coresight_tmc_dev_s *)csdev; + int ret = 0; + + if (tmcdev->refcnt++ == 0) + { + ret = coresight_claim_device(tmcdev->csdev.addr); + if (ret < 0) + { + tmcdev->refcnt--; + cserr("%s claimed failed\n", csdev->name); + return ret; + } + + ret = tmc_etf_link_hw_enable(tmcdev); + if (ret < 0) + { + tmcdev->refcnt--; + coresight_disclaim_device(tmcdev->csdev.addr); + cserr("%s enable failed\n", csdev->name); + } + } + + return ret; +} + +/**************************************************************************** + * Name: tmc_etf_link_disable + ****************************************************************************/ + +static void tmc_etf_link_disable(FAR struct coresight_dev_s *csdev, + int iport, int oport) +{ + FAR struct coresight_tmc_dev_s *tmcdev = + (FAR struct coresight_tmc_dev_s *)csdev; + + if (--tmcdev->refcnt == 0) + { + tmc_etf_hw_disable(tmcdev); + coresight_disclaim_device(tmcdev->csdev.addr); + csinfo("%s disabled\n", csdev->name); + } +} + +/**************************************************************************** + * Name: tmc_etf_open + ****************************************************************************/ + +static int tmc_etf_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct coresight_tmc_dev_s *tmcdev; + int ret; + + DEBUGASSERT(inode->i_private); + tmcdev = (FAR struct coresight_tmc_dev_s *)inode->i_private; + + ret = nxmutex_lock(&tmcdev->lock); + if (ret < 0) + { + return ret; + } + + if (tmcdev->opencnt++ == 0) + { + tmcdev->buf = kmm_zalloc(tmcdev->size); + if (tmcdev->buf == NULL) + { + cserr("malloc buffer failed\n"); + tmcdev->opencnt--; + ret = -ENOMEM; + } + else + { + irqstate_t flags; + + flags = enter_critical_section(); + if (tmcdev->refcnt > 0) + { + tmc_etf_hw_disable_and_read(tmcdev); + tmc_etf_sink_hw_enable(tmcdev); + } + else + { + /* ETF devices can not read buffer directly when it is not + * enabled like etb device does. Its buffer needs to be + * captured in stopped state which is transferred after it + * hase been enabled. + */ + + kmm_free(tmcdev->buf); + tmcdev->opencnt--; + ret = -EACCES; + } + + leave_critical_section(flags); + } + } + + nxmutex_unlock(&tmcdev->lock); + return ret; +} + +/**************************************************************************** + * Name: tmc_etf_close + ****************************************************************************/ + +static int tmc_etf_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct coresight_tmc_dev_s *tmcdev; + int ret; + + DEBUGASSERT(inode->i_private); + tmcdev = (FAR struct coresight_tmc_dev_s *)inode->i_private; + + ret = nxmutex_lock(&tmcdev->lock); + if (ret < 0) + { + return ret; + } + + if (--tmcdev->opencnt == 0) + { + kmm_free(tmcdev->buf); + } + + nxmutex_unlock(&tmcdev->lock); + return ret; +} + +/**************************************************************************** + * Name: tmc_etf_read + ****************************************************************************/ + +static ssize_t tmc_etf_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct coresight_tmc_dev_s *tmcdev; + + DEBUGASSERT(inode->i_private); + tmcdev = (FAR struct coresight_tmc_dev_s *)inode->i_private; + + if (filep->f_pos > tmcdev->len) + { + return 0; + } + + if (filep->f_pos + buflen > tmcdev->len) + { + buflen = tmcdev->len - filep->f_pos; + } + + memcpy(buffer, (FAR char *)tmcdev->buf + filep->f_pos, buflen); + filep->f_pos += buflen; + + return buflen; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tmc_etf_register + ****************************************************************************/ + +int tmc_etf_register(FAR struct coresight_tmc_dev_s * tmcdev, + FAR const struct coresight_desc_s *desc) +{ + int ret; + + if (desc->type == CORESIGHT_DEV_TYPE_SINK) + { + enum coresight_dev_subtype_sink_e subtype = desc->subtype.sink_subtype; + char pathname[TMC_MAX_NAME_LEN]; + + if ((subtype != CORESIGHT_DEV_SUBTYPE_SINK_TMC_BUFFER) && + (subtype != CORESIGHT_DEV_SUBTYPE_SINK_TMC_ETF)) + { + cserr("unsupported tmc device type\n"); + return -EPERM; + } + + tmcdev->csdev.ops = &g_tmc_sink_ops; + ret = coresight_register(&tmcdev->csdev, desc); + if (ret < 0) + { + cserr("%s:coresight register failed\n", desc->name); + return ret; + } + + snprintf(pathname, sizeof(pathname), "/dev/%s", desc->name); + ret = register_driver(pathname, &g_tmc_fops, 0444, tmcdev); + if (ret < 0) + { + cserr("%s:driver register failed\n", desc->name); + coresight_unregister(&tmcdev->csdev); + return ret; + } + } + else if (desc->type == CORESIGHT_DEV_TYPE_LINK) + { + if (desc->subtype.link_subtype != CORESIGHT_DEV_SUBTYPE_LINK_FIFO) + { + cserr("unsupported tmc link device type\n"); + return -EPERM; + } + + tmcdev->csdev.ops = &g_tmc_link_ops; + ret = coresight_register(&tmcdev->csdev, desc); + if (ret < 0) + { + cserr("%s:coresight register failed\n", desc->name); + return ret; + } + } + else + { + cserr("unsupported tmc device type\n"); + return -EPERM; + } + + return 0; +} + +/**************************************************************************** + * Name: tmc_etf_unregister + ****************************************************************************/ + +void tmc_etf_unregister(FAR struct coresight_tmc_dev_s * tmcdev) +{ + if (tmcdev->csdev.type == CORESIGHT_DEV_TYPE_SINK) + { + char pathname[TMC_MAX_NAME_LEN]; + + snprintf(pathname, sizeof(pathname), "/dev/%s", tmcdev->csdev.name); + unregister_driver(pathname); + } + + coresight_unregister(&tmcdev->csdev); +} diff --git a/drivers/coresight/coresight_tmc_etr.c b/drivers/coresight/coresight_tmc_etr.c new file mode 100644 index 00000000000..37ea6d23df1 --- /dev/null +++ b/drivers/coresight/coresight_tmc_etr.c @@ -0,0 +1,522 @@ +/**************************************************************************** + * drivers/coresight/coresight_tmc_etr.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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "coresight_common.h" +#include "coresight_tmc_core.h" + +/**************************************************************************** + * Private Functions Prototypes + ****************************************************************************/ + +static int tmc_etr_enable(FAR struct coresight_dev_s *csdev); +static void tmc_etr_disable(FAR struct coresight_dev_s *csdev); + +static int tmc_etr_open(FAR struct file *filep); +static int tmc_etr_close(FAR struct file *filep); +static ssize_t tmc_etr_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct coresight_sink_ops_s g_tmc_etr_sink_ops = +{ + .enable = tmc_etr_enable, + .disable = tmc_etr_disable, +}; + +static const struct coresight_ops_s g_tmc_sink_ops = +{ + .sink_ops = &g_tmc_etr_sink_ops, +}; + +static const struct file_operations g_tmc_fops = +{ + tmc_etr_open, /* open */ + tmc_etr_close, /* close */ + tmc_etr_read, /* read */ + NULL, /* write */ + NULL, /* seek */ + NULL, /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tmc_etr_hw_enable + ****************************************************************************/ + +static int tmc_etr_hw_enable(FAR struct coresight_tmc_dev_s *tmcdev) +{ + uint32_t axictl; + + coresight_unlock(tmcdev->csdev.addr); + + /* Wait for TMCSReady bit to be set. */ + + if (coresight_timeout(TMC_STS_TMCREADY, TMC_STS_TMCREADY, + tmcdev->csdev.addr + TMC_STS) < 0) + { + cserr("tmc device is not ready\n"); + coresight_lock(tmcdev->csdev.addr); + return -EAGAIN; + } + + coresight_put32(tmcdev->size / 4, tmcdev->csdev.addr + TMC_RSZ); + coresight_put32(TMC_MODE_CIRCULAR_BUFFER, tmcdev->csdev.addr + TMC_MODE); + + /* Set AXICTL. */ + + axictl = coresight_get32(tmcdev->csdev.addr + TMC_AXICTL); + axictl &= ~TMC_AXICTL_CLEAR_MASK; + axictl |= TMC_AXICTL_PROT_CTL_B1; + axictl |= TMC_AXICTL_WR_BURST(tmcdev->burst_size); + axictl |= TMC_AXICTL_AXCACHE_OS; + if (tmcdev->caps & TMC_ETR_AXI_ARCACHE) + { + axictl &= ~TMC_AXICTL_ARCACHE_MASK; + axictl |= TMC_AXICTL_ARCACHE_OS; + } + + if (tmcdev->mode == TMC_ETR_MODE_ETR_SG) + { + axictl |= TMC_AXICTL_SCT_GAT_MODE; + } + + coresight_put32(axictl, tmcdev->csdev.addr + TMC_AXICTL); + coresight_put32((uintptr_t)tmcdev->buf, tmcdev->csdev.addr + TMC_DBALO); + coresight_put32(((uint64_t)(uintptr_t)tmcdev->buf) >> 32, + tmcdev->csdev.addr + TMC_DBAHI); + + if (tmcdev->caps & TMC_ETR_SAVE_RESTORE) + { + coresight_put32((uint32_t)tmcdev->buf, tmcdev->csdev.addr + TMC_RRP); + coresight_put32(((uint64_t)(uintptr_t)tmcdev->buf >> 32), + tmcdev->csdev.addr + TMC_RRPHI); + + coresight_put32((uint32_t)tmcdev->buf, tmcdev->csdev.addr + TMC_RWP); + coresight_put32(((uint64_t)(uintptr_t)tmcdev->buf >> 32), + tmcdev->csdev.addr + TMC_RWPHI); + + coresight_modify32(0x0, TMC_STS_FULL, tmcdev->csdev.addr + TMC_STS); + } + + coresight_put32(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI | TMC_FFCR_FON_FLIN | + TMC_FFCR_FON_TRIG_EVT | TMC_FFCR_TRIGON_TRIGIN, + tmcdev->csdev.addr + TMC_FFCR); + coresight_put32(tmcdev->trigger_cntr, tmcdev->csdev.addr + TMC_TRG); + + /* Enable capture. */ + + coresight_put32(TMC_CTL_CAPT_EN, tmcdev->csdev.addr + TMC_CTL); + + coresight_lock(tmcdev->csdev.addr); + return 0; +} + +/**************************************************************************** + * Name: tmc_flush_and_stop + ****************************************************************************/ + +static void tmc_flush_and_stop(FAR struct coresight_tmc_dev_s *tmcdev) +{ + coresight_modify32(TMC_FFCR_STOP_ON_FLUSH, TMC_FFCR_STOP_ON_FLUSH, + tmcdev->csdev.addr + TMC_FFCR); + coresight_modify32(TMC_FFCR_FON_MAN, TMC_FFCR_FON_MAN, + tmcdev->csdev.addr + TMC_FFCR); + if (coresight_timeout(0x0, TMC_FFCR_FON_MAN, + tmcdev->csdev.addr + TMC_FFCR) < 0) + { + cserr("timeout while waiting for completion of Manual Flush\n"); + } + + if (coresight_timeout(TMC_STS_TMCREADY, TMC_STS_TMCREADY, + tmcdev->csdev.addr + TMC_STS) < 0) + { + cserr("timeout while waiting for TMC to be Ready\n"); + } +} + +/**************************************************************************** + * Name: tmc_etr_hw_read + ****************************************************************************/ + +static void tmc_etr_hw_read(FAR struct coresight_tmc_dev_s *tmcdev) +{ + uintptr_t rrp; + uintptr_t rwp; + uint32_t status; + bool lost = false; + + rrp = (uint64_t)coresight_get32(tmcdev->csdev.addr + TMC_RRPHI) << 32 | + coresight_get32(tmcdev->csdev.addr + TMC_RRP); + rwp = (uint64_t)coresight_get32(tmcdev->csdev.addr + TMC_RWPHI) << 32 | + coresight_get32(tmcdev->csdev.addr + TMC_RWP); + status = coresight_get32(tmcdev->csdev.addr + TMC_STS); + + /* If there were memory errors in the session, truncate the buffer. */ + + if (status & TMC_STS_MEMERR) + { + cserr("tmc memory error detected, truncating buffer\n"); + tmcdev->len = 0; + return; + } + + if ((status & TMC_STS_FULL) == 1) + { + lost = true; + } + + tmcdev->offset = rrp - (uintptr_t)tmcdev->buf; + if (lost == true) + { + tmcdev->len = tmcdev->size; + } + else + { + tmcdev->len = (uint32_t)(rwp - rrp); + } + + if (tmcdev->offset + tmcdev->len > tmcdev->size) + { + up_invalidate_dcache((uintptr_t)tmcdev->buf, tmcdev->size); + } + else + { + up_invalidate_dcache((uintptr_t)((FAR char *)tmcdev->buf + + tmcdev->offset), tmcdev->len); + } + + if (lost == true) + { + coresight_insert_barrier_packet((FAR char *)tmcdev->buf + + tmcdev->offset); + } +} + +/**************************************************************************** + * Name: tmc_etr_hw_disable_and_read + ****************************************************************************/ + +static void +tmc_etr_hw_disable_and_read(FAR struct coresight_tmc_dev_s *tmcdev) +{ + coresight_unlock(tmcdev->csdev.addr); + tmc_flush_and_stop(tmcdev); + tmc_etr_hw_read(tmcdev); + + /* Disable capture enable bit. */ + + coresight_put32(0x0, tmcdev->csdev.addr + TMC_CTL); + coresight_lock(tmcdev->csdev.addr); +} + +/**************************************************************************** + * Name: tmc_etr_hw_disable + ****************************************************************************/ + +static void tmc_etr_hw_disable(FAR struct coresight_tmc_dev_s *tmcdev) +{ + coresight_unlock(tmcdev->csdev.addr); + tmc_flush_and_stop(tmcdev); + + /* Disable capture enable bit. */ + + coresight_put32(0x0, tmcdev->csdev.addr + TMC_CTL); + coresight_lock(tmcdev->csdev.addr); +} + +/**************************************************************************** + * Name: tmc_etr_enable + ****************************************************************************/ + +static int tmc_etr_enable(FAR struct coresight_dev_s *csdev) +{ + FAR struct coresight_tmc_dev_s *tmcdev = + (FAR struct coresight_tmc_dev_s *)csdev; + int ret = 0; + + if (tmcdev->refcnt++ == 0) + { + ret = coresight_claim_device(tmcdev->csdev.addr); + if (ret < 0) + { + tmcdev->refcnt--; + cserr("%s claimed failed\n", csdev->name); + return ret; + } + + ret = tmc_etr_hw_enable(tmcdev); + if (ret < 0) + { + tmcdev->refcnt--; + coresight_disclaim_device(tmcdev->csdev.addr); + cserr("%s enabled failed\n", csdev->name); + } + } + + return ret; +} + +/**************************************************************************** + * Name: tmc_etr_disable + ****************************************************************************/ + +static void tmc_etr_disable(FAR struct coresight_dev_s *csdev) +{ + FAR struct coresight_tmc_dev_s *tmcdev = + (FAR struct coresight_tmc_dev_s *)csdev; + + if (--tmcdev->refcnt == 0) + { + tmc_etr_hw_disable(tmcdev); + coresight_disclaim_device(tmcdev->csdev.addr); + csinfo("%s disabled\n", csdev->name); + } +} + +/**************************************************************************** + * Name: tmc_etr_open + * + * Description: + * TMC etr devices write data directly to system memory, it can not enable + * after disable like tmc_etf_open does, which may cause data confusion. + * + ****************************************************************************/ + +static int tmc_etr_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct coresight_tmc_dev_s *tmcdev; + int ret; + + DEBUGASSERT(inode->i_private); + tmcdev = (FAR struct coresight_tmc_dev_s *)inode->i_private; + + ret = nxmutex_lock(&tmcdev->lock); + if (ret < 0) + { + return ret; + } + + if (tmcdev->opencnt++ == 0) + { + irqstate_t flags; + + flags = enter_critical_section(); + if (tmcdev->refcnt > 0) + { + tmc_etr_hw_disable_and_read(tmcdev); + } + else + { + /* ETR devices can not read buffer directly when it is not + * enabled like etb device does. Its buffer needs to be + * captured in stopped state which is transferred after it + * hase been enabled. + */ + + tmcdev->opencnt--; + ret = -EACCES; + } + + leave_critical_section(flags); + } + + nxmutex_unlock(&tmcdev->lock); + return ret; +} + +/**************************************************************************** + * Name: tmc_etr_close + ****************************************************************************/ + +static int tmc_etr_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct coresight_tmc_dev_s *tmcdev; + int ret; + + DEBUGASSERT(inode->i_private); + tmcdev = (FAR struct coresight_tmc_dev_s *)inode->i_private; + + ret = nxmutex_lock(&tmcdev->lock); + if (ret < 0) + { + return ret; + } + + if (--tmcdev->opencnt == 0) + { + irqstate_t flags; + + flags = enter_critical_section(); + if (tmcdev->refcnt > 0) + { + if (tmc_etr_hw_enable(tmcdev) < 0) + { + cserr("%s enabled failed after read\n", tmcdev->csdev.name); + } + } + + leave_critical_section(flags); + } + + nxmutex_unlock(&tmcdev->lock); + return ret; +} + +/**************************************************************************** + * Name: tmc_etr_read + ****************************************************************************/ + +static ssize_t tmc_etr_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct coresight_tmc_dev_s *tmcdev; + off_t off; + + DEBUGASSERT(inode->i_private); + tmcdev = (FAR struct coresight_tmc_dev_s *)inode->i_private; + + if (filep->f_pos > tmcdev->len) + { + return 0; + } + + if (filep->f_pos + buflen > tmcdev->len) + { + buflen = tmcdev->len - filep->f_pos; + } + + /* Compute the offset from which we read the data. */ + + off = tmcdev->offset + filep->f_pos; + if (off >= tmcdev->size) + { + off -= tmcdev->size; + } + + /* Adjust the length to limit this transaction to end of buffer. */ + + if (buflen > tmcdev->size - off) + { + buflen = tmcdev->size - off; + } + + memcpy(buffer, (FAR char *)tmcdev->buf + off, buflen); + filep->f_pos += buflen; + + return buflen; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tmc_etr_register + ****************************************************************************/ + +int tmc_etr_register(FAR struct coresight_tmc_dev_s *tmcdev, + FAR const struct coresight_desc_s *desc) +{ + char pathname[TMC_MAX_NAME_LEN]; + int ret; + + /* Check for AXI access. */ + + if ((coresight_get32(desc->addr + TMC_AUTHSTATUS) & + TMC_AUTH_NSID_MASK) != TMC_NSID_EN) + { + return -EACCES; + } + + if (desc->subtype.sink_subtype != CORESIGHT_DEV_SUBTYPE_SINK_TMC_SYSMEM) + { + cserr("unsupported tmc device type\n"); + return -EPERM; + } + + tmcdev->mode = TMC_ETR_MODE_FLAT; + tmcdev->buf = kmm_zalloc(tmcdev->size); + if (tmcdev->buf == NULL) + { + return -ENOMEM; + } + + tmcdev->csdev.ops = &g_tmc_sink_ops; + ret = coresight_register(&tmcdev->csdev, desc); + if (ret < 0) + { + cserr("%s:coresight register failed\n", desc->name); + goto cs_err; + } + + snprintf(pathname, sizeof(pathname), "/dev/%s", desc->name); + ret = register_driver(pathname, &g_tmc_fops, 0444, tmcdev); + if (ret < 0) + { + cserr("%s:driver register failed\n", desc->name); + goto drv_err; + } + + return ret; + +drv_err: + coresight_unregister(&tmcdev->csdev); +cs_err: + kmm_free(tmcdev->buf); + return ret; +} + +/**************************************************************************** + * Name: tmc_etr_unregister + ****************************************************************************/ + +void tmc_etr_unregister(FAR struct coresight_tmc_dev_s * tmcdev) +{ + char pathname[TMC_MAX_NAME_LEN]; + + snprintf(pathname, sizeof(pathname), "/dev/%s", tmcdev->csdev.name); + unregister_driver(pathname); + coresight_unregister(&tmcdev->csdev); + kmm_free(tmcdev->buf); +} diff --git a/include/nuttx/coresight/coresight.h b/include/nuttx/coresight/coresight.h index 178a3323044..9261cafd578 100644 --- a/include/nuttx/coresight/coresight.h +++ b/include/nuttx/coresight/coresight.h @@ -54,13 +54,16 @@ enum coresight_dev_subtype_link_e { CORESIGHT_DEV_SUBTYPE_LINK_MERG, /* Funnel */ CORESIGHT_DEV_SUBTYPE_LINK_SPLIT, /* Replocator */ - CORESIGHT_DEV_SUBTYPE_LINK_FIFO, /* TMC ETR */ + CORESIGHT_DEV_SUBTYPE_LINK_FIFO, /* TMC ETF */ }; enum coresight_dev_subtype_sink_e { CORESIGHT_DEV_SUBTYPE_SINK_PORT, /* TPIU */ CORESIGHT_DEV_SUBTYPE_SINK_BUFFER, /* ETB */ + CORESIGHT_DEV_SUBTYPE_SINK_TMC_BUFFER, /* TMC ETB */ + CORESIGHT_DEV_SUBTYPE_SINK_TMC_SYSMEM, /* TMC ETR */ + CORESIGHT_DEV_SUBTYPE_SINK_TMC_ETF, /* TMC ETF */ }; /* This structure is used to unify different subtype of devices. */ @@ -137,6 +140,11 @@ struct coresight_desc_s uintptr_t stimulus_port_addr; + /* Used in TMC-ETR device. */ + + uint32_t buffer_size; + uint32_t burst_size; + /* Description of outports of current device. */ int outport_num; diff --git a/include/nuttx/coresight/coresight_tmc.h b/include/nuttx/coresight/coresight_tmc.h new file mode 100644 index 00000000000..64fc2d6d41e --- /dev/null +++ b/include/nuttx/coresight/coresight_tmc.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * include/nuttx/coresight/coresight_tmc.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_TMC_H +#define __INCLUDE_NUTTX_CORESIGHT_CORESIGHT_TMC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +enum tmc_config_type_e +{ + TMC_CONFIG_TYPE_ETB, + TMC_CONFIG_TYPE_ETR, + TMC_CONFIG_TYPE_ETF, +}; + +enum tmc_mem_intf_width_e +{ + TMC_MEM_INTF_WIDTH_32BITS = 1, + TMC_MEM_INTF_WIDTH_64BITS = 2, + TMC_MEM_INTF_WIDTH_128BITS = 4, + TMC_MEM_INTF_WIDTH_256BITS = 8, +}; + +enum tmc_etr_mode_e +{ + TMC_ETR_MODE_FLAT, /* Uses contiguous flat buffer. */ + TMC_ETR_MODE_ETR_SG, /* Uses in-built TMC ETR SG mechanism. */ + TMC_ETR_MODE_CATU, /* Use SG mechanism in CATU. */ +}; + +struct coresight_tmc_dev_s +{ + struct coresight_dev_s csdev; + enum tmc_config_type_e config_type; /* Device type: ETB/ETR/ETF. */ + enum tmc_mem_intf_width_e mmwidth; /* Width of the memory interface databus, in bytes. */ + uint32_t trigger_cntr; /* Amount of words to store after a trigger. */ + uint32_t size; /* RAM buffer size. */ + uint32_t burst_size; /* Max burst size used in ETR devices. */ + FAR uint32_t *buf; /* Pointer to the RAM buf. */ + uint32_t len; /* Valid data len in RAM buffer. */ + mutex_t lock; /* Mutex for driver's open/close. */ + uint32_t caps; /* Capalilities current etr device has. */ + enum tmc_etr_mode_e mode; /* ETR buffer mode. */ + uint32_t offset; /* Data offset in ETR buffer. */ + uint8_t refcnt; /* TMC coresight device's enable count */ + uint8_t opencnt; /* TMC device's open count. */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: tmc_register + * + * Description: + * Register a TMC devices. + * + * Input Parameters: + * desc - A description of this coresight device. + * + * Returned Value: + * Pointer to a TMC device on success; NULL on failure. + * + ****************************************************************************/ + +FAR struct coresight_tmc_dev_s * +tmc_register(FAR const struct coresight_desc_s *desc); + +/**************************************************************************** + * Name: tmc_unregister + * + * Description: + * Unregister a TMC devices. + * + * Input Parameters: + * tmcdev - Pointer to the TMC device. + * + ****************************************************************************/ + +void tmc_unregister(FAR struct coresight_tmc_dev_s *tmcdev); + +#endif //__INCLUDE_NUTTX_CORESIGHT_CORESIGHT_TMC_H