diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index 35e0899f10be..38bb4a282778 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -99,6 +99,7 @@ config CORESIGHT_STM depends on (ARM && !(CPU_32v3 || CPU_32v4 || CPU_32v4T)) || ARM64 select CORESIGHT_LINKS_AND_SINKS select STM + select CORESIGHT_OST if CORESIGHT_QGKI help This driver provides support for hardware assisted software instrumentation based tracing. This is primarily used for @@ -183,4 +184,12 @@ config CORESIGHT_TGU provide a trigger point for centering data around a specific event within the trace data buffer. +config CORESIGHT_OST + bool "CoreSight OST framework" + depends on CORESIGHT_STM && COREISGHT_QGKI + help + This driver enables the support for Open System Trace packets in STM. + This is primarily intended to be used as a layer on top of underlying + physical byte transport mechanisms.The additional header can be used + to provide more information. endif diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index 964db14b284d..f0cd9dfcd7a8 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -24,3 +24,4 @@ obj-$(CONFIG_CORESIGHT_HWEVENT) += coresight-hwevent.o obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o obj-$(CONFIG_CORESIGHT_CSR) += coresight-csr.o obj-$(CONFIG_CORESIGHT_TGU) += coresight-tgu.o +obj-$(CONFIG_CORESIGHT_OST) += coresight-ost.o diff --git a/drivers/hwtracing/coresight/coresight-ost.c b/drivers/hwtracing/coresight/coresight-ost.c new file mode 100644 index 000000000000..c719e36e451c --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-ost.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include "coresight-ost.h" +#include + +#define STM_USERSPACE_HEADER_SIZE (8) +#define STM_USERSPACE_MAGIC1_VAL (0xf0) +#define STM_USERSPACE_MAGIC2_VAL (0xf1) + +#define OST_TOKEN_STARTSIMPLE (0x10) +#define OST_VERSION_MIPI1 (16) + +#define STM_MAKE_VERSION(ma, mi) ((ma << 8) | mi) +#define STM_HEADER_MAGIC (0x5953) + +#define STM_FLAG_MARKED BIT(4) + +#define STM_TRACE_BUF_SIZE 4096 + +static struct stm_drvdata *stmdrvdata; + +static uint32_t stm_channel_alloc(void) +{ + struct stm_drvdata *drvdata = stmdrvdata; + uint32_t ch, off, num_ch_per_cpu; + int cpu; + + num_ch_per_cpu = drvdata->numsp/num_present_cpus(); + + cpu = get_cpu(); + + off = num_ch_per_cpu * cpu; + ch = find_next_zero_bit(drvdata->chs.bitmap, + drvdata->numsp, off); + if (unlikely(ch >= (off + num_ch_per_cpu))) { + put_cpu(); + return drvdata->numsp; + } + + set_bit(ch, drvdata->chs.bitmap); + put_cpu(); + + return ch; +} + +static int stm_ost_send(void __iomem *addr, const void *data, uint32_t size) +{ + uint32_t len = size; + + if (((unsigned long)data & 0x1) && (size >= 1)) { + writeb_relaxed_no_log(*(uint8_t *)data, addr); + data++; + size--; + } + if (((unsigned long)data & 0x2) && (size >= 2)) { + writew_relaxed_no_log(*(uint16_t *)data, addr); + data += 2; + size -= 2; + } + + /* now we are 32bit aligned */ + while (size >= 4) { + writel_relaxed_no_log(*(uint32_t *)data, addr); + data += 4; + size -= 4; + } + + if (size >= 2) { + writew_relaxed_no_log(*(uint16_t *)data, addr); + data += 2; + size -= 2; + } + if (size >= 1) { + writeb_relaxed_no_log(*(uint8_t *)data, addr); + data++; + size--; + } + + return len; +} + +static void stm_channel_free(uint32_t ch) +{ + struct stm_drvdata *drvdata = stmdrvdata; + + clear_bit(ch, drvdata->chs.bitmap); +} + +static int stm_trace_ost_header(void __iomem *ch_addr, uint32_t flags, + uint8_t entity_id, uint8_t proto_id) +{ + void __iomem *addr; + uint32_t header; + char *hdr; + + hdr = (char *)&header; + + hdr[0] = OST_TOKEN_STARTSIMPLE; + hdr[1] = OST_VERSION_MIPI1; + hdr[2] = entity_id; + hdr[3] = proto_id; + + /* header is expected to be D32M type */ + flags |= STM_FLAG_MARKED; + flags &= ~STM_FLAG_TIMESTAMPED; + addr = (void __iomem *)(ch_addr + + stm_channel_off(STM_PKT_TYPE_DATA, flags)); + + return stm_ost_send(addr, &header, sizeof(header)); +} + +static int stm_trace_data_header(void __iomem *addr) +{ + char hdr[24]; + int len = 0; + + *(uint16_t *)(hdr) = STM_MAKE_VERSION(0, 2); + *(uint16_t *)(hdr + 2) = STM_HEADER_MAGIC; + *(uint32_t *)(hdr + 4) = raw_smp_processor_id(); + *(uint64_t *)(hdr + 8) = sched_clock(); + *(uint64_t *)(hdr + 16) = task_tgid_nr(get_current()); + + len += stm_ost_send(addr, hdr, sizeof(hdr)); + len += stm_ost_send(addr, current->comm, TASK_COMM_LEN); + + return len; +} + +static int stm_trace_data(void __iomem *ch_addr, uint32_t flags, + const void *data, uint32_t size) +{ + void __iomem *addr; + int len = 0; + + flags &= ~STM_FLAG_TIMESTAMPED; + addr = (void __iomem *)(ch_addr + + stm_channel_off(STM_PKT_TYPE_DATA, flags)); + + /* send the data header */ + len += stm_trace_data_header(addr); + /* send the actual data */ + len += stm_ost_send(addr, data, size); + + return len; +} + +static int stm_trace_ost_tail(void __iomem *ch_addr, uint32_t flags) +{ + void __iomem *addr; + uint32_t tail = 0x0; + + addr = (void __iomem *)(ch_addr + + stm_channel_off(STM_PKT_TYPE_FLAG, flags)); + + return stm_ost_send(addr, &tail, sizeof(tail)); +} + +static inline int __stm_trace(uint32_t flags, uint8_t entity_id, + uint8_t proto_id, const void *data, uint32_t size) +{ + struct stm_drvdata *drvdata = stmdrvdata; + int len = 0; + uint32_t ch; + void __iomem *ch_addr; + + /* allocate channel and get the channel address */ + ch = stm_channel_alloc(); + if (unlikely(ch >= drvdata->numsp)) { + drvdata->ch_alloc_fail_count++; + dev_err_ratelimited(&drvdata->csdev->dev, + "Channel allocation failed %d", + drvdata->ch_alloc_fail_count); + return 0; + } + + ch_addr = (void __iomem *)stm_channel_addr(drvdata, ch); + + /* send the ost header */ + len += stm_trace_ost_header(ch_addr, flags, entity_id, + proto_id); + + /* send the payload data */ + len += stm_trace_data(ch_addr, flags, data, size); + + /* send the ost tail */ + len += stm_trace_ost_tail(ch_addr, flags); + + /* we are done, free the channel */ + stm_channel_free(ch); + + return len; +} + +/* + * stm_trace - trace the binary or string data through STM + * @flags: tracing options - guaranteed, timestamped, etc + * @entity_id: entity representing the trace data + * @proto_id: protocol id to distinguish between different binary formats + * @data: pointer to binary or string data buffer + * @size: size of data to send + * + * Packetizes the data as the payload to an OST packet and sends it over STM + * + * CONTEXT: + * Can be called from any context. + * + * RETURNS: + * number of bytes transferred over STM + */ +int stm_trace(uint32_t flags, uint8_t entity_id, uint8_t proto_id, + const void *data, uint32_t size) +{ + struct stm_drvdata *drvdata = stmdrvdata; + + /* we don't support sizes more than 24bits (0 to 23) */ + if (!(drvdata && drvdata->enable && + test_bit(entity_id, drvdata->entities) && size && + (size < 0x1000000))) + return 0; + + return __stm_trace(flags, entity_id, proto_id, data, size); +} +EXPORT_SYMBOL(stm_trace); + +ssize_t stm_ost_packet(struct stm_data *stm_data, + unsigned int size, + const unsigned char *buf) +{ + struct stm_drvdata *drvdata = container_of(stm_data, + struct stm_drvdata, stm); + + uint8_t entity_id, proto_id; + uint32_t flags; + + if (!drvdata->enable || !size) + return -EINVAL; + + if (size > STM_TRACE_BUF_SIZE) + size = STM_TRACE_BUF_SIZE; + + if (size >= STM_USERSPACE_HEADER_SIZE && + buf[0] == STM_USERSPACE_MAGIC1_VAL && + buf[1] == STM_USERSPACE_MAGIC2_VAL) { + + entity_id = buf[2]; + proto_id = buf[3]; + flags = *(uint32_t *)(buf + 4); + + if (!test_bit(entity_id, drvdata->entities) || + !(size - STM_USERSPACE_HEADER_SIZE)) { + return size; + } + + __stm_trace(flags, entity_id, proto_id, + buf + STM_USERSPACE_HEADER_SIZE, + size - STM_USERSPACE_HEADER_SIZE); + } else { + if (!test_bit(OST_ENTITY_DEV_NODE, drvdata->entities)) + return size; + + __stm_trace(STM_FLAG_TIMESTAMPED, OST_ENTITY_DEV_NODE, 0, + buf, size); + } + + return size; +} +EXPORT_SYMBOL(stm_ost_packet); + +int stm_set_ost_params(struct device *dev, struct stm_drvdata *drvdata, + size_t bitmap_size) +{ + drvdata->chs.bitmap = devm_kzalloc(dev, bitmap_size, + GFP_KERNEL); + if (!drvdata->chs.bitmap) + return -ENOMEM; + + bitmap_fill(drvdata->entities, OST_ENTITY_MAX); + stmdrvdata = drvdata; + + return 0; +} +EXPORT_SYMBOL(stm_set_ost_params); + diff --git a/drivers/hwtracing/coresight/coresight-ost.h b/drivers/hwtracing/coresight/coresight-ost.h new file mode 100644 index 000000000000..df96ec96393b --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-ost.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + */ + +#ifndef _CORESIGHT_CORESIGHT_OST_H +#define _CORESIGHT_CORESIGHT_OST_H + +#include +#include + +#ifdef CONFIG_CORESIGHT_OST +static inline bool stm_ost_configured(void) { return true; } + +extern ssize_t stm_ost_packet(struct stm_data *stm_data, + unsigned int size, + const unsigned char *buf); + +extern int stm_set_ost_params(struct device *dev, struct stm_drvdata *drvdata, + size_t bitmap_size); +#else +static inline bool stm_ost_configured(void) { return false; } + +static inline ssize_t stm_ost_packet(struct stm_data *stm_data, + unsigned int size, + const unsigned char *buf) +{ + return 0; +} + +static inline int stm_set_ost_params(struct stm_drvdata *drvdata, + size_t bitmap_size) +{ + return 0; +} +#endif +#endif diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index b908ca104645..2555ff27686a 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * Description: CoreSight System Trace Macrocell driver * @@ -30,6 +30,7 @@ #include #include +#include "coresight-ost.h" #include "coresight-priv.h" #define STMDMASTARTR 0xc04 @@ -67,8 +68,6 @@ #define STMITATBCTR0 0xef8 #define STM_32_CHANNEL 32 -#define BYTES_PER_CHANNEL 256 -#define STM_TRACE_BUF_SIZE 4096 #define STM_SW_MASTER_END 127 /* Register bit definition */ @@ -76,15 +75,7 @@ /* Reserve the first 10 channels for kernel usage */ #define STM_CHANNEL_OFFSET 0 -enum stm_pkt_type { - STM_PKT_TYPE_DATA = 0x98, - STM_PKT_TYPE_FLAG = 0xE8, - STM_PKT_TYPE_TRIG = 0xF8, -}; - -#define stm_channel_addr(drvdata, ch) (drvdata->chs.base + \ - (ch * BYTES_PER_CHANNEL)) -#define stm_channel_off(type, opts) (type & ~opts) +DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm"); static int boot_nr_channel; @@ -96,56 +87,6 @@ module_param_named( boot_nr_channel, boot_nr_channel, int, S_IRUGO ); -/** - * struct channel_space - central management entity for extended ports - * @base: memory mapped base address where channels start. - * @phys: physical base address of channel region. - * @guaraneed: is the channel delivery guaranteed. - */ -struct channel_space { - void __iomem *base; - phys_addr_t phys; - unsigned long *guaranteed; -}; - -DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm"); - -/** - * struct stm_drvdata - specifics associated to an STM component - * @base: memory mapped base address for this component. - * @atclk: optional clock for the core parts of the STM. - * @csdev: component vitals needed by the framework. - * @spinlock: only one at a time pls. - * @chs: the channels accociated to this STM. - * @stm: structure associated to the generic STM interface. - * @mode: this tracer's mode, i.e sysFS, or disabled. - * @traceid: value of the current ID for this component. - * @write_bytes: Maximus bytes this STM can write at a time. - * @stmsper: settings for register STMSPER. - * @stmspscr: settings for register STMSPSCR. - * @numsp: the total number of stimulus port support by this STM. - * @stmheer: settings for register STMHEER. - * @stmheter: settings for register STMHETER. - * @stmhebsr: settings for register STMHEBSR. - */ -struct stm_drvdata { - void __iomem *base; - struct clk *atclk; - struct coresight_device *csdev; - spinlock_t spinlock; - struct channel_space chs; - struct stm_data stm; - local_t mode; - u8 traceid; - u32 write_bytes; - u32 stmsper; - u32 stmspscr; - u32 numsp; - u32 stmheer; - u32 stmheter; - u32 stmhebsr; -}; - static void stm_hwevent_enable_hw(struct stm_drvdata *drvdata) { CS_UNLOCK(drvdata->base); @@ -210,6 +151,7 @@ static int stm_enable(struct coresight_device *csdev, spin_lock(&drvdata->spinlock); stm_enable_hw(drvdata); + drvdata->enable = true; spin_unlock(&drvdata->spinlock); dev_dbg(&csdev->dev, "STM tracing enabled\n"); @@ -267,6 +209,7 @@ static void stm_disable(struct coresight_device *csdev, if (local_read(&drvdata->mode) == CS_MODE_SYSFS) { spin_lock(&drvdata->spinlock); stm_disable_hw(drvdata); + drvdata->enable = false; spin_unlock(&drvdata->spinlock); /* Wait until the engine has completely stopped */ @@ -350,7 +293,11 @@ static void stm_generic_unlink(struct stm_data *stm_data, struct stm_drvdata, stm); if (!drvdata || !drvdata->csdev) return; - +#ifdef CONFIG_CORESIGHT_QGKI + /* If any OST entity is enabled do not disable the device */ + if (!bitmap_empty(drvdata->entities, OST_ENTITY_MAX)) + return; +#endif coresight_disable(drvdata->csdev); } @@ -630,6 +577,53 @@ static ssize_t traceid_store(struct device *dev, } static DEVICE_ATTR_RW(traceid); +#ifdef CONFIG_CORESIGHT_QGKI +static ssize_t entities_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t len; + + len = scnprintf(buf, PAGE_SIZE, "%*pb\n", + OST_ENTITY_MAX, drvdata->entities); + + if (PAGE_SIZE - len < 2) + len = -EINVAL; + else + len += scnprintf(buf + len, 2, "\n"); + + return len; +} + +static ssize_t entities_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent); + unsigned long val1, val2; + + if (sscanf(buf, "%lx %lx", &val1, &val2) != 2) + return -EINVAL; + + if (val1 >= OST_ENTITY_MAX) + return -EINVAL; + + if (!stm_ost_configured()) + return -EPERM; + + if (val2) + __set_bit(val1, drvdata->entities); + else + __clear_bit(val1, drvdata->entities); + + return size; +} +static DEVICE_ATTR_RW(entities); + +#define coresight_stm_simple_func(name, offset) \ + +#endif + #define coresight_stm_reg(name, offset) \ coresight_simple_reg32(struct stm_drvdata, name, offset) @@ -652,6 +646,9 @@ static struct attribute *coresight_stm_attrs[] = { &dev_attr_port_enable.attr, &dev_attr_port_select.attr, &dev_attr_traceid.attr, +#ifdef CONFIG_CORESIGHT_QGKI + &dev_attr_entities.attr, +#endif NULL, }; @@ -803,7 +800,7 @@ static u32 stm_num_stimulus_port(struct stm_drvdata *drvdata) numsp &= 0x1ffff; if (!numsp) numsp = STM_32_CHANNEL; - return numsp; + return STM_32_CHANNEL; } static void stm_init_default_data(struct stm_drvdata *drvdata) @@ -818,12 +815,12 @@ static void stm_init_default_data(struct stm_drvdata *drvdata) drvdata->stmsper = ~0x0; /* - * The trace ID value for *ETM* tracers start at CPU_ID * 2 + 0x10 and - * anything equal to or higher than 0x70 is reserved. Since 0x00 is - * also reserved the STM trace ID needs to be higher than 0x00 and - * lowner than 0x10. + * The trace ID value for *ETM* tracers start at CPU_ID + 0x1 and + * anything equal to or higher than 0x70 is reserved. Since 0x00 is + * also reserved the STM trace ID needs to be higher than number + * of cpu i.e 0x8 in our case and lower than 0x70. */ - drvdata->traceid = 0x1; + drvdata->traceid = 0x10; /* Set invariant transaction timing on all channels */ bitmap_clear(drvdata->chs.guaranteed, 0, drvdata->numsp); @@ -842,6 +839,10 @@ static void stm_init_generic_data(struct stm_drvdata *drvdata, drvdata->stm.sw_end = 1; drvdata->stm.hw_override = true; drvdata->stm.sw_nchannels = drvdata->numsp; +#ifdef CONFIG_CORESIGHT_QGKI + drvdata->stm.ost_configured = stm_ost_configured; + drvdata->stm.ost_packet = stm_ost_packet; +#endif drvdata->stm.sw_mmiosz = BYTES_PER_CHANNEL; drvdata->stm.packet = stm_generic_packet; drvdata->stm.mmio_addr = stm_mmio_addr; @@ -902,6 +903,12 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id) drvdata->numsp = stm_num_stimulus_port(drvdata); bitmap_size = BITS_TO_LONGS(drvdata->numsp) * sizeof(long); +#ifdef CONFIG_CORESIGHT_QGKI + /* Store the driver data pointer for use in exported functions */ + ret = stm_set_ost_params(dev, drvdata, bitmap_size); + if (ret) + return ret; +#endif guaranteed = devm_kzalloc(dev, bitmap_size, GFP_KERNEL); if (!guaranteed) diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c index 603b83ac5085..a2809b9b8fb0 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -580,7 +580,25 @@ ssize_t notrace stm_data_write(struct stm_data *data, unsigned int m, unsigned int flags = ts_first ? STP_PACKET_TIMESTAMPED : 0; ssize_t sz; size_t pos; +#ifdef CONFIG_CORESIGHT_QGKI + if (data->ost_configured()) { + pos = data->ost_packet(data, count, buf); + sz = 0; + } else { + for (pos = 0, sz = 0; pos < count; pos += sz) { + sz = min_t(unsigned int, count - pos, 8); + sz = data->packet(data, m, c, STP_PACKET_DATA, flags, + sz, &((u8 *)buf)[pos]); + if (sz <= 0) + break; + if (ts_first) { + flags = 0; + ts_first = false; + } + } + } +#else for (pos = 0, sz = 0; pos < count; pos += sz) { sz = min_t(unsigned int, count - pos, 8); sz = data->packet(data, m, c, STP_PACKET_DATA, flags, sz, @@ -593,7 +611,7 @@ ssize_t notrace stm_data_write(struct stm_data *data, unsigned int m, ts_first = false; } } - +#endif return sz < 0 ? sz : pos; } EXPORT_SYMBOL_GPL(stm_data_write); diff --git a/include/linux/coresight-stm.h b/include/linux/coresight-stm.h index 74714b59f9d2..e073bdb3ab6d 100644 --- a/include/linux/coresight-stm.h +++ b/include/linux/coresight-stm.h @@ -1,7 +1,111 @@ /* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2011-2012, 2017, The Linux Foundation. All rights reserved. + */ #ifndef __LINUX_CORESIGHT_STM_H_ #define __LINUX_CORESIGHT_STM_H_ +#include +#include +#include #include +#define BYTES_PER_CHANNEL 256 + +enum stm_pkt_type { + STM_PKT_TYPE_DATA = 0x98, + STM_PKT_TYPE_FLAG = 0xE8, + STM_PKT_TYPE_TRIG = 0xF8, +}; + +#define stm_channel_off(type, opts) (type & ~opts) + +#define stm_channel_addr(drvdata, ch) (drvdata->chs.base + \ + (ch * BYTES_PER_CHANNEL)) + +#define stm_log_inv(entity_id, proto_id, data, size) \ + stm_trace(STM_FLAG_NONE, entity_id, proto_id, data, size) + +#define stm_log_inv_ts(entity_id, proto_id, data, size) \ + stm_trace(STM_FLAG_TIMESTAMPED, entity_id, proto_id, \ + data, size) + +#define stm_log_gtd(entity_id, proto_id, data, size) \ + stm_trace(STM_FLAG_GUARANTEED, entity_id, proto_id, \ + data, size) + +#define stm_log_gtd_ts(entity_id, proto_id, data, size) \ + stm_trace(STM_FLAG_GUARANTEED | STM_OPTION_TIMESTAMPED, \ + entity_id, proto_id, data, size) + +#define stm_log(entity_id, data, size) \ + stm_log_inv_ts(entity_id, 0, data, size) + +/** + * struct channel_space - central management entity for extended ports + * @base: memory mapped base address where channels start. + * @phys: physical base address of channel region. + * @guaraneed: is the channel delivery guaranteed. + * @bitmap: channel info for OST packet + */ +struct channel_space { + void __iomem *base; + phys_addr_t phys; + unsigned long *guaranteed; + unsigned long *bitmap; +}; + +/** + * struct stm_drvdata - specifics associated to an STM component + * @base: memory mapped base address for this component. + * @dev: the device entity associated to this component. + * @atclk: optional clock for the core parts of the STM. + * @csdev: component vitals needed by the framework. + * @spinlock: only one at a time pls. + * @chs: the channels accociated to this STM. + * @entities currently configured OST entities. + * @stm: structure associated to the generic STM interface. + * @mode: this tracer's mode, i.e sysFS, or disabled. + * @traceid: value of the current ID for this component. + * @write_bytes: Maximus bytes this STM can write at a time. + * @stmsper: settings for register STMSPER. + * @stmspscr: settings for register STMSPSCR. + * @numsp: the total number of stimulus port support by this STM. + * @stmheer: settings for register STMHEER. + * @stmheter: settings for register STMHETER. + * @stmhebsr: settings for register STMHEBSR. + * @ch_alloc_fail_count: Number of ch allocation failures over time. + */ +struct stm_drvdata { + void __iomem *base; + struct clk *atclk; + struct coresight_device *csdev; + spinlock_t spinlock; + struct channel_space chs; + bool enable; + DECLARE_BITMAP(entities, OST_ENTITY_MAX); + struct stm_data stm; + local_t mode; + u8 traceid; + u32 write_bytes; + u32 stmsper; + u32 stmspscr; + u32 numsp; + u32 stmheer; + u32 stmheter; + u32 stmhebsr; + u32 ch_alloc_fail_count; +}; + +#if defined(CONFIG_CORESIGHT_STM) && defined(CONFIG_CORESIGHT_QGKI) +extern int stm_trace(uint32_t flags, uint8_t entity_id, uint8_t proto_id, + const void *data, uint32_t size); + +#else +static inline int stm_trace(uint32_t flags, uint8_t entity_id, + uint8_t proto_id, const void *data, uint32_t size) +{ + return 0; +} +#endif #endif diff --git a/include/linux/stm.h b/include/linux/stm.h index c6f577ab6f21..3b75b959304d 100644 --- a/include/linux/stm.h +++ b/include/linux/stm.h @@ -80,6 +80,12 @@ struct stm_data { unsigned int sw_nchannels; unsigned int sw_mmiosz; unsigned int hw_override; +#ifdef CONFIG_CORESIGHT_QGKI + bool (*ost_configured)(void); + ssize_t (*ost_packet)(struct stm_data *stm_data, + unsigned int size, + const unsigned char *buf); +#endif ssize_t (*packet)(struct stm_data *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, diff --git a/include/uapi/linux/coresight-stm.h b/include/uapi/linux/coresight-stm.h index aac550a52f80..b55b35965590 100644 --- a/include/uapi/linux/coresight-stm.h +++ b/include/uapi/linux/coresight-stm.h @@ -2,9 +2,18 @@ #ifndef __UAPI_CORESIGHT_STM_H_ #define __UAPI_CORESIGHT_STM_H_ -#define STM_FLAG_TIMESTAMPED BIT(3) -#define STM_FLAG_GUARANTEED BIT(7) +#define STM_FLAG_NONE 0x00 +#define STM_FLAG_TIMESTAMPED 0x08 +#define STM_FLAG_GUARANTEED 0x80 +#define OST_ENTITY_NONE 0x00 +#define OST_ENTITY_FTRACE_EVENTS 0x01 +#define OST_ENTITY_TRACE_PRINTK 0x02 +#define OST_ENTITY_TRACE_MARKER 0x04 +#define OST_ENTITY_DEV_NODE 0x08 +#define OST_ENTITY_DIAG 0xEE +#define OST_ENTITY_QVIEW 0xFE +#define OST_ENTITY_MAX 0xFF /* * The CoreSight STM supports guaranteed and invariant timing * transactions. Guaranteed transactions are guaranteed to be