coresight: Add snapshot of Coresight TPDM and TPDA driver

Add snapshot for coresight TPDM and TPDA driver from msm-4.19
commit 64be469bda3ae ("power: smb1390-psy: Configure IREV
and main's ICL to prevent IREV condition").
Make necessary change to adopt coresight framework change.
Remove extra clock and regulator control for compilation.
Remove module param.

Change-Id: I4795841a2fdffe59e8fe88534c95e48898c0b8bc
Signed-off-by: Tingwei Zhang <tingwei@codeaurora.org>
This commit is contained in:
Tingwei Zhang 2019-08-07 19:23:47 +08:00
parent 13538105c7
commit a47c331396
4 changed files with 5072 additions and 0 deletions

View File

@ -109,4 +109,30 @@ config CORESIGHT_CPU_DEBUG
properly, please refer Documentation/trace/coresight-cpu-debug.txt
for detailed description and the example for usage.
config CORESIGHT_TPDA
bool "CoreSight Trace, Profiling & Diagnostics Aggregator driver"
help
This driver provides support for configuring aggregator. This is
primarily useful for pulling the data sets from one or more
attached monitors and pushing the resultant data out. Multiple
monitors are connected on different input ports of TPDA.
config CORESIGHT_TPDM
bool "CoreSight Trace, Profiling & Diagnostics Monitor driver"
help
This driver provides support for configuring monitor. Monitors are
primarily responsible for data set collection and support the
ability to collect any permutation of data set types. Monitors are
also responsible for interaction with system cross triggering.
config CORESIGHT_TPDM_DEFAULT_ENABLE
bool "Turn on TPDM tracing by default"
depends on CORESIGHT_TPDM
help
Turns on CoreSight TPDM tracing for different data set types by
default. Otherwise, tracing is disabled by default but can be
enabled via sysfs.
If unsure, say 'N' here to avoid potential power and performance
penalty.
endif

View File

@ -17,3 +17,5 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \
obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o
obj-$(CONFIG_CORESIGHT_CATU) += coresight-catu.o
obj-$(CONFIG_CORESIGHT_TPDA) += coresight-tpda.o
obj-$(CONFIG_CORESIGHT_TPDM) += coresight-tpdm.o

View File

@ -0,0 +1,828 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/bitmap.h>
#include <linux/of.h>
#include <linux/coresight.h>
#include "coresight-priv.h"
#define tpda_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
#define tpda_readl(drvdata, off) __raw_readl(drvdata->base + off)
#define TPDA_LOCK(drvdata) \
do { \
mb(); /* ensure configuration take effect before we lock it */ \
tpda_writel(drvdata, 0x0, CORESIGHT_LAR); \
} while (0)
#define TPDA_UNLOCK(drvdata) \
do { \
tpda_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
mb(); /* ensure unlock take effect before we configure */ \
} while (0)
#define TPDA_CR (0x000)
#define TPDA_Pn_CR(n) (0x004 + (n * 4))
#define TPDA_FPID_CR (0x084)
#define TPDA_FREQREQ_VAL (0x088)
#define TPDA_SYNCR (0x08C)
#define TPDA_FLUSH_CR (0x090)
#define TPDA_FLUSH_SR (0x094)
#define TPDA_FLUSH_ERR (0x098)
#define TPDA_MAX_INPORTS 32
DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
struct tpda_drvdata {
void __iomem *base;
struct device *dev;
struct coresight_device *csdev;
struct mutex lock;
bool enable;
uint32_t atid;
uint32_t bc_esize[TPDA_MAX_INPORTS];
uint32_t tc_esize[TPDA_MAX_INPORTS];
uint32_t dsb_esize[TPDA_MAX_INPORTS];
uint32_t cmb_esize[TPDA_MAX_INPORTS];
bool trig_async;
bool trig_flag_ts;
bool trig_freq;
bool freq_ts;
uint32_t freq_req_val;
bool freq_req;
bool cmbchan_mode;
};
static void __tpda_enable_pre_port(struct tpda_drvdata *drvdata)
{
uint32_t val;
val = tpda_readl(drvdata, TPDA_CR);
/* Set the master id */
val = val & ~(0x7F << 13);
val = val & ~(0x7F << 6);
val |= (drvdata->atid << 6);
if (drvdata->trig_async)
val = val | BIT(5);
else
val = val & ~BIT(5);
if (drvdata->trig_flag_ts)
val = val | BIT(4);
else
val = val & ~BIT(4);
if (drvdata->trig_freq)
val = val | BIT(3);
else
val = val & ~BIT(3);
if (drvdata->freq_ts)
val = val | BIT(2);
else
val = val & ~BIT(2);
if (drvdata->cmbchan_mode)
val = val | BIT(20);
else
val = val & ~BIT(20);
tpda_writel(drvdata, val, TPDA_CR);
/*
* If FLRIE bit is set, set the master and channel
* id as zero
*/
if (BVAL(tpda_readl(drvdata, TPDA_CR), 4))
tpda_writel(drvdata, 0x0, TPDA_FPID_CR);
}
static void __tpda_enable_port(struct tpda_drvdata *drvdata, int port)
{
uint32_t val;
val = tpda_readl(drvdata, TPDA_Pn_CR(port));
if (drvdata->bc_esize[port] == 32)
val = val & ~BIT(4);
else if (drvdata->bc_esize[port] == 64)
val = val | BIT(4);
if (drvdata->tc_esize[port] == 32)
val = val & ~BIT(5);
else if (drvdata->tc_esize[port] == 64)
val = val | BIT(5);
if (drvdata->dsb_esize[port] == 32)
val = val & ~BIT(8);
else if (drvdata->dsb_esize[port] == 64)
val = val | BIT(8);
val = val & ~(0x3 << 6);
if (drvdata->cmb_esize[port] == 8)
val &= ~(0x3 << 6);
else if (drvdata->cmb_esize[port] == 32)
val |= (0x1 << 6);
else if (drvdata->cmb_esize[port] == 64)
val |= (0x2 << 6);
/* Set the hold time */
val = val & ~(0x7 << 1);
val |= (0x5 << 1);
tpda_writel(drvdata, val, TPDA_Pn_CR(port));
/* Enable the port */
val = val | BIT(0);
tpda_writel(drvdata, val, TPDA_Pn_CR(port));
}
static void __tpda_enable_post_port(struct tpda_drvdata *drvdata)
{
uint32_t val;
val = tpda_readl(drvdata, TPDA_SYNCR);
/* Clear the mode */
val = val & ~BIT(12);
/* Program the counter value */
val = val | 0xFFF;
tpda_writel(drvdata, val, TPDA_SYNCR);
if (drvdata->freq_req_val)
tpda_writel(drvdata, drvdata->freq_req_val, TPDA_FREQREQ_VAL);
else
tpda_writel(drvdata, 0x0, TPDA_FREQREQ_VAL);
val = tpda_readl(drvdata, TPDA_CR);
if (drvdata->freq_req)
val = val | BIT(1);
else
val = val & ~BIT(1);
tpda_writel(drvdata, val, TPDA_CR);
}
static void __tpda_enable(struct tpda_drvdata *drvdata, int port)
{
TPDA_UNLOCK(drvdata);
if (!drvdata->enable)
__tpda_enable_pre_port(drvdata);
__tpda_enable_port(drvdata, port);
if (!drvdata->enable)
__tpda_enable_post_port(drvdata);
TPDA_LOCK(drvdata);
}
static int tpda_enable(struct coresight_device *csdev, int inport, int outport)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
mutex_lock(&drvdata->lock);
__tpda_enable(drvdata, inport);
drvdata->enable = true;
mutex_unlock(&drvdata->lock);
dev_info(drvdata->dev, "TPDA inport %d enabled\n", inport);
return 0;
}
static void __tpda_disable(struct tpda_drvdata *drvdata, int port)
{
uint32_t val;
TPDA_UNLOCK(drvdata);
val = tpda_readl(drvdata, TPDA_Pn_CR(port));
val = val & ~BIT(0);
tpda_writel(drvdata, val, TPDA_Pn_CR(port));
TPDA_LOCK(drvdata);
}
static void tpda_disable(struct coresight_device *csdev, int inport,
int outport)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
mutex_lock(&drvdata->lock);
__tpda_disable(drvdata, inport);
drvdata->enable = false;
mutex_unlock(&drvdata->lock);
dev_info(drvdata->dev, "TPDA inport %d disabled\n", inport);
}
static const struct coresight_ops_link tpda_link_ops = {
.enable = tpda_enable,
.disable = tpda_disable,
};
static const struct coresight_ops tpda_cs_ops = {
.link_ops = &tpda_link_ops,
};
static ssize_t trig_async_enable_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
return scnprintf(buf, PAGE_SIZE, "%u\n",
(unsigned int)drvdata->trig_async);
}
static ssize_t trig_async_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (kstrtoul(buf, 16, &val))
return -EINVAL;
mutex_lock(&drvdata->lock);
if (val)
drvdata->trig_async = true;
else
drvdata->trig_async = false;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR_RW(trig_async_enable);
static ssize_t trig_flag_ts_enable_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
return scnprintf(buf, PAGE_SIZE, "%u\n",
(unsigned int)drvdata->trig_flag_ts);
}
static ssize_t trig_flag_ts_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (kstrtoul(buf, 16, &val))
return -EINVAL;
mutex_lock(&drvdata->lock);
if (val)
drvdata->trig_flag_ts = true;
else
drvdata->trig_flag_ts = false;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR_RW(trig_flag_ts_enable);
static ssize_t trig_freq_enable_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
return scnprintf(buf, PAGE_SIZE, "%u\n",
(unsigned int)drvdata->trig_freq);
}
static ssize_t trig_freq_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (kstrtoul(buf, 16, &val))
return -EINVAL;
mutex_lock(&drvdata->lock);
if (val)
drvdata->trig_freq = true;
else
drvdata->trig_freq = false;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR_RW(trig_freq_enable);
static ssize_t freq_ts_enable_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
return scnprintf(buf, PAGE_SIZE, "%u\n",
(unsigned int)drvdata->freq_ts);
}
static ssize_t freq_ts_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (kstrtoul(buf, 16, &val))
return -EINVAL;
mutex_lock(&drvdata->lock);
if (val)
drvdata->freq_ts = true;
else
drvdata->freq_ts = false;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR_RW(freq_ts_enable);
static ssize_t freq_req_val_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->freq_req_val;
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static ssize_t freq_req_val_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (kstrtoul(buf, 16, &val))
return -EINVAL;
mutex_lock(&drvdata->lock);
drvdata->freq_req_val = val;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR_RW(freq_req_val);
static ssize_t freq_req_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
return scnprintf(buf, PAGE_SIZE, "%u\n",
(unsigned int)drvdata->freq_req);
}
static ssize_t freq_req_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (kstrtoul(buf, 16, &val))
return -EINVAL;
mutex_lock(&drvdata->lock);
if (val)
drvdata->freq_req = true;
else
drvdata->freq_req = false;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR_RW(freq_req);
static ssize_t global_flush_req_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
mutex_lock(&drvdata->lock);
if (!drvdata->enable) {
mutex_unlock(&drvdata->lock);
return -EPERM;
}
TPDA_UNLOCK(drvdata);
val = tpda_readl(drvdata, TPDA_CR);
TPDA_LOCK(drvdata);
mutex_unlock(&drvdata->lock);
return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
}
static ssize_t global_flush_req_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (kstrtoul(buf, 16, &val))
return -EINVAL;
mutex_lock(&drvdata->lock);
if (!drvdata->enable) {
mutex_unlock(&drvdata->lock);
return -EPERM;
}
if (val) {
TPDA_UNLOCK(drvdata);
val = tpda_readl(drvdata, TPDA_CR);
val = val | BIT(0);
tpda_writel(drvdata, val, TPDA_CR);
TPDA_LOCK(drvdata);
}
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR_RW(global_flush_req);
static ssize_t port_flush_req_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
mutex_lock(&drvdata->lock);
if (!drvdata->enable) {
mutex_unlock(&drvdata->lock);
return -EPERM;
}
TPDA_UNLOCK(drvdata);
val = tpda_readl(drvdata, TPDA_FLUSH_CR);
TPDA_LOCK(drvdata);
mutex_unlock(&drvdata->lock);
return scnprintf(buf, PAGE_SIZE, "%lx\n", val);
}
static ssize_t port_flush_req_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (kstrtoul(buf, 16, &val))
return -EINVAL;
mutex_lock(&drvdata->lock);
if (!drvdata->enable) {
mutex_unlock(&drvdata->lock);
return -EPERM;
}
if (val) {
TPDA_UNLOCK(drvdata);
tpda_writel(drvdata, val, TPDA_FLUSH_CR);
TPDA_LOCK(drvdata);
}
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR_RW(port_flush_req);
static ssize_t cmbchan_mode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
return scnprintf(buf, PAGE_SIZE, "%u\n",
(unsigned int)drvdata->cmbchan_mode);
}
static ssize_t cmbchan_mode_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t size)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent);
bool val;
if (kstrtobool(buf, &val))
return -EINVAL;
mutex_lock(&drvdata->lock);
if (val)
drvdata->cmbchan_mode = true;
else
drvdata->cmbchan_mode = false;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR_RW(cmbchan_mode);
static struct attribute *tpda_attrs[] = {
&dev_attr_trig_async_enable.attr,
&dev_attr_trig_flag_ts_enable.attr,
&dev_attr_trig_freq_enable.attr,
&dev_attr_freq_ts_enable.attr,
&dev_attr_freq_req_val.attr,
&dev_attr_freq_req.attr,
&dev_attr_global_flush_req.attr,
&dev_attr_port_flush_req.attr,
&dev_attr_cmbchan_mode.attr,
NULL,
};
static struct attribute_group tpda_attr_grp = {
.attrs = tpda_attrs,
};
static const struct attribute_group *tpda_attr_grps[] = {
&tpda_attr_grp,
NULL,
};
static int tpda_parse_tc(struct tpda_drvdata *drvdata)
{
int len, port, i;
const __be32 *prop;
struct device_node *node = drvdata->dev->of_node;
prop = of_get_property(node, "qcom,tc-elem-size", &len);
if (prop) {
len /= sizeof(__be32);
if (len < 2 || len > 63 || len % 2 != 0) {
dev_err(drvdata->dev,
"Dataset TC width entries are wrong\n");
return -EINVAL;
}
for (i = 0; i < len; i++) {
port = be32_to_cpu(prop[i++]);
if (port >= TPDA_MAX_INPORTS) {
dev_err(drvdata->dev,
"Wrong port specified for TC\n");
return -EINVAL;
}
drvdata->tc_esize[port] = be32_to_cpu(prop[i]);
}
}
return 0;
}
static int tpda_parse_bc(struct tpda_drvdata *drvdata)
{
int len, port, i;
const __be32 *prop;
struct device_node *node = drvdata->dev->of_node;
prop = of_get_property(node, "qcom,bc-elem-size", &len);
if (prop) {
len /= sizeof(__be32);
if (len < 2 || len > 63 || len % 2 != 0) {
dev_err(drvdata->dev,
"Dataset BC width entries are wrong\n");
return -EINVAL;
}
for (i = 0; i < len; i++) {
port = be32_to_cpu(prop[i++]);
if (port >= TPDA_MAX_INPORTS) {
dev_err(drvdata->dev,
"Wrong port specified for BC\n");
return -EINVAL;
}
drvdata->bc_esize[port] = be32_to_cpu(prop[i]);
}
}
return 0;
}
static int tpda_parse_dsb(struct tpda_drvdata *drvdata)
{
int len, port, i;
const __be32 *prop;
struct device_node *node = drvdata->dev->of_node;
prop = of_get_property(node, "qcom,dsb-elem-size", &len);
if (prop) {
len /= sizeof(__be32);
if (len < 2 || len > 63 || len % 2 != 0) {
dev_err(drvdata->dev,
"Dataset DSB width entries are wrong\n");
return -EINVAL;
}
for (i = 0; i < len; i++) {
port = be32_to_cpu(prop[i++]);
if (port >= TPDA_MAX_INPORTS) {
dev_err(drvdata->dev,
"Wrong port specified for DSB\n");
return -EINVAL;
}
drvdata->dsb_esize[port] = be32_to_cpu(prop[i]);
}
}
return 0;
}
static int tpda_parse_cmb(struct tpda_drvdata *drvdata)
{
int len, port, i;
const __be32 *prop;
struct device_node *node = drvdata->dev->of_node;
prop = of_get_property(node, "qcom,cmb-elem-size", &len);
if (prop) {
len /= sizeof(__be32);
if (len < 2 || len > 63 || len % 2 != 0) {
dev_err(drvdata->dev,
"Dataset CMB width entries are wrong\n");
return -EINVAL;
}
for (i = 0; i < len; i++) {
port = be32_to_cpu(prop[i++]);
if (port >= TPDA_MAX_INPORTS) {
dev_err(drvdata->dev,
"Wrong port specified for CMB\n");
return -EINVAL;
}
drvdata->cmb_esize[port] = be32_to_cpu(prop[i]);
}
}
return 0;
}
static int tpda_parse_of_data(struct tpda_drvdata *drvdata)
{
int ret;
struct device_node *node = drvdata->dev->of_node;
ret = of_property_read_u32(node, "qcom,tpda-atid", &drvdata->atid);
if (ret) {
dev_err(drvdata->dev, "TPDA ATID is not specified\n");
return -EINVAL;
}
ret = tpda_parse_tc(drvdata);
if (ret) {
dev_err(drvdata->dev, "Dataset TC width entries are wrong\n");
return -EINVAL;
}
ret = tpda_parse_bc(drvdata);
if (ret) {
dev_err(drvdata->dev, "Dataset BC width entries are wrong\n");
return -EINVAL;
}
ret = tpda_parse_dsb(drvdata);
if (ret) {
dev_err(drvdata->dev, "Dataset DSB width entries are wrong\n");
return -EINVAL;
}
ret = tpda_parse_cmb(drvdata);
if (ret) {
dev_err(drvdata->dev, "Dataset CMB width entries are wrong\n");
return -EINVAL;
}
return 0;
}
static void tpda_init_default_data(struct tpda_drvdata *drvdata)
{
drvdata->freq_ts = true;
}
static bool coresight_authstatus_enabled(void __iomem *addr)
{
int ret;
unsigned int auth_val;
if (!addr)
return false;
auth_val = readl_relaxed(addr + CORESIGHT_AUTHSTATUS);
if ((BMVAL(auth_val, 0, 1) == 0x2) ||
(BMVAL(auth_val, 2, 3) == 0x2) ||
(BMVAL(auth_val, 4, 5) == 0x2) ||
(BMVAL(auth_val, 6, 7) == 0x2))
ret = false;
else
ret = true;
return ret;
}
static int tpda_probe(struct amba_device *adev, const struct amba_id *id)
{
int ret;
struct device *dev = &adev->dev;
struct coresight_platform_data *pdata;
struct tpda_drvdata *drvdata;
struct coresight_desc desc = { 0 };
desc.name = coresight_alloc_device_name(&tpda_devs, dev);
if (!desc.name)
return -ENOMEM;
pdata = coresight_get_platform_data(dev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
adev->dev.platform_data = pdata;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
drvdata->dev = &adev->dev;
dev_set_drvdata(dev, drvdata);
drvdata->base = devm_ioremap_resource(dev, &adev->res);
if (!drvdata->base)
return -ENOMEM;
mutex_init(&drvdata->lock);
ret = tpda_parse_of_data(drvdata);
if (ret)
return ret;
if (!coresight_authstatus_enabled(drvdata->base))
goto err;
tpda_init_default_data(drvdata);
desc.type = CORESIGHT_DEV_TYPE_LINK;
desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
desc.ops = &tpda_cs_ops;
desc.pdata = adev->dev.platform_data;
desc.dev = &adev->dev;
desc.groups = tpda_attr_grps;
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
pm_runtime_put(&adev->dev);
dev_dbg(drvdata->dev, "TPDA initialized\n");
return 0;
err:
return -EPERM;
}
static struct amba_id tpda_ids[] = {
{
.id = 0x0003b969,
.mask = 0x0003ffff,
.data = "TPDA",
},
{ 0, 0},
};
static struct amba_driver tpda_driver = {
.drv = {
.name = "coresight-tpda",
.owner = THIS_MODULE,
.suppress_bind_attrs = true,
},
.probe = tpda_probe,
.id_table = tpda_ids,
};
builtin_amba_driver(tpda_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Aggregator driver");

File diff suppressed because it is too large Load Diff