Coresight: Add TPDA link driver

TPDA(Trace, Profiling and Diagnostics Aggregator) is
to provide packetization, funneling and timestamping of
TPDM data. Multiple monitors are connected to different
input ports of TPDA.This change is to add tpda
enable/disable/probe functions for coresight tpda driver.

 - - - -         - - - -        - - - -
| TPDM 0|      | TPDM 1 |     | TPDM 2|
 - - - -         - - - -        - - - -
    |               |             |
    |_ _ _ _ _ _    |     _ _ _ _ |
                |   |    |
                |   |    |
           ------------------
          |        TPDA      |
           ------------------

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Tao Zhang <quic_taozha@quicinc.com>
Signed-off-by: Mao Jinlong <quic_jinlmao@quicinc.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20230120095301.30792-2-quic_jinlmao@quicinc.com
This commit is contained in:
Mao Jinlong 2023-01-17 06:57:05 -08:00 committed by Suzuki K Poulose
parent 436cca9a2c
commit 5b7916625c
4 changed files with 258 additions and 0 deletions

View File

@ -217,6 +217,7 @@ config ULTRASOC_SMB
config CORESIGHT_TPDM
tristate "CoreSight Trace, Profiling & Diagnostics Monitor driver"
select CORESIGHT_LINKS_AND_SINKS
select CORESIGHT_TPDA
help
This driver provides support for configuring monitor. Monitors are
primarily responsible for data set collection and support the
@ -225,4 +226,14 @@ config CORESIGHT_TPDM
To compile this driver as a module, choose M here: the module will be
called coresight-tpdm.
config CORESIGHT_TPDA
tristate "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.
To compile this driver as a module, choose M here: the module will be
called coresight-tpda.
endif

View File

@ -26,6 +26,7 @@ obj-$(CONFIG_CORESIGHT_CATU) += coresight-catu.o
obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o
obj-$(CONFIG_CORESIGHT_TRBE) += coresight-trbe.o
obj-$(CONFIG_CORESIGHT_TPDM) += coresight-tpdm.o
obj-$(CONFIG_CORESIGHT_TPDA) += coresight-tpda.o
coresight-cti-y := coresight-cti-core.o coresight-cti-platform.o \
coresight-cti-sysfs.o
obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o

View File

@ -0,0 +1,211 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/amba/bus.h>
#include <linux/bitfield.h>
#include <linux/coresight.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include "coresight-priv.h"
#include "coresight-tpda.h"
#include "coresight-trace-id.h"
DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
/* Settings pre enabling port control register */
static void tpda_enable_pre_port(struct tpda_drvdata *drvdata)
{
u32 val;
val = readl_relaxed(drvdata->base + TPDA_CR);
val &= ~TPDA_CR_ATID;
val |= FIELD_PREP(TPDA_CR_ATID, drvdata->atid);
writel_relaxed(val, drvdata->base + TPDA_CR);
}
static void tpda_enable_port(struct tpda_drvdata *drvdata, int port)
{
u32 val;
val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port));
/* Enable the port */
val |= TPDA_Pn_CR_ENA;
writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
}
static void __tpda_enable(struct tpda_drvdata *drvdata, int port)
{
CS_UNLOCK(drvdata->base);
if (!drvdata->csdev->enable)
tpda_enable_pre_port(drvdata);
tpda_enable_port(drvdata, port);
CS_LOCK(drvdata->base);
}
static int tpda_enable(struct coresight_device *csdev, int inport, int outport)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
spin_lock(&drvdata->spinlock);
if (atomic_read(&csdev->refcnt[inport]) == 0)
__tpda_enable(drvdata, inport);
atomic_inc(&csdev->refcnt[inport]);
spin_unlock(&drvdata->spinlock);
dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", inport);
return 0;
}
static void __tpda_disable(struct tpda_drvdata *drvdata, int port)
{
u32 val;
CS_UNLOCK(drvdata->base);
val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port));
val &= ~TPDA_Pn_CR_ENA;
writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
CS_LOCK(drvdata->base);
}
static void tpda_disable(struct coresight_device *csdev, int inport,
int outport)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
spin_lock(&drvdata->spinlock);
if (atomic_dec_return(&csdev->refcnt[inport]) == 0)
__tpda_disable(drvdata, inport);
spin_unlock(&drvdata->spinlock);
dev_dbg(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 int tpda_init_default_data(struct tpda_drvdata *drvdata)
{
int atid;
/*
* TPDA must has a unique atid. This atid can uniquely
* identify the TPDM trace source connected to the TPDA.
* The TPDMs which are connected to same TPDA share the
* same trace-id. When TPDA does packetization, different
* port will have unique channel number for decoding.
*/
atid = coresight_trace_id_get_system_id();
if (atid < 0)
return atid;
drvdata->atid = atid;
return 0;
}
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 };
void __iomem *base;
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);
base = devm_ioremap_resource(dev, &adev->res);
if (!base)
return -ENOMEM;
drvdata->base = base;
spin_lock_init(&drvdata->spinlock);
ret = tpda_init_default_data(drvdata);
if (ret)
return ret;
desc.name = coresight_alloc_device_name(&tpda_devs, dev);
if (!desc.name)
return -ENOMEM;
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.access = CSDEV_ACCESS_IOMEM(base);
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;
}
static void __exit tpda_remove(struct amba_device *adev)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(&adev->dev);
coresight_trace_id_put_system_id(drvdata->atid);
coresight_unregister(drvdata->csdev);
}
/*
* Different TPDA has different periph id.
* The difference is 0-7 bits' value. So ignore 0-7 bits.
*/
static struct amba_id tpda_ids[] = {
{
.id = 0x000f0f00,
.mask = 0x000fff00,
},
{ 0, 0},
};
static struct amba_driver tpda_driver = {
.drv = {
.name = "coresight-tpda",
.owner = THIS_MODULE,
.suppress_bind_attrs = true,
},
.probe = tpda_probe,
.remove = tpda_remove,
.id_table = tpda_ids,
};
module_amba_driver(tpda_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Aggregator driver");

View File

@ -0,0 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _CORESIGHT_CORESIGHT_TPDA_H
#define _CORESIGHT_CORESIGHT_TPDA_H
#define TPDA_CR (0x000)
#define TPDA_Pn_CR(n) (0x004 + (n * 4))
/* Aggregator port enable bit */
#define TPDA_Pn_CR_ENA BIT(0)
#define TPDA_MAX_INPORTS 32
/* Bits 6 ~ 12 is for atid value */
#define TPDA_CR_ATID GENMASK(12, 6)
/**
* struct tpda_drvdata - specifics associated to an TPDA component
* @base: memory mapped base address for this component.
* @dev: The device entity associated to this component.
* @csdev: component vitals needed by the framework.
* @spinlock: lock for the drvdata value.
* @enable: enable status of the component.
*/
struct tpda_drvdata {
void __iomem *base;
struct device *dev;
struct coresight_device *csdev;
spinlock_t spinlock;
u8 atid;
};
#endif /* _CORESIGHT_CORESIGHT_TPDA_H */