coresight: ost: Add snapshot of Coresight OST driver
This is a snapshot of the coresight-cti driver as of msm-4.14 commit '7d42028b99d32ad6ec82aa429378fba0280a1c4a'.byte-cntr: Read 64bit rwp TMC RWP has two 32bit registers which combine to one 64bit register. Read correct RWP register in byte counter driver. Make necessary change to adopt coresight framework change. Change-Id: I4a89b9b041c354093b96e01ee0436a7372ff37fd Signed-off-by: Rama Aparna Mallavarapu <aparnam@codeaurora.org> Signed-off-by: Mulu He <muluhe@codeaurora.org> Signed-off-by: Tingwei Zhang <tingwei@codeaurora.org>
This commit is contained in:
parent
a3ccff9799
commit
2aa23d3acc
@ -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
|
||||
|
@ -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
|
||||
|
290
drivers/hwtracing/coresight/coresight-ost.c
Normal file
290
drivers/hwtracing/coresight/coresight-ost.c
Normal file
@ -0,0 +1,290 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/coresight.h>
|
||||
#include "coresight-ost.h"
|
||||
#include <linux/sched/clock.h>
|
||||
|
||||
#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);
|
||||
|
37
drivers/hwtracing/coresight/coresight-ost.h
Normal file
37
drivers/hwtracing/coresight/coresight-ost.h
Normal file
@ -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 <linux/types.h>
|
||||
#include <linux/coresight-stm.h>
|
||||
|
||||
#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
|
@ -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 <linux/pm_runtime.h>
|
||||
#include <linux/stm.h>
|
||||
|
||||
#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)
|
||||
|
@ -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);
|
||||
|
@ -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 <asm/local.h>
|
||||
#include <linux/stm.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <uapi/linux/coresight-stm.h>
|
||||
|
||||
#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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user