Skip to content

Commit 4bba4b9

Browse files
Songwei Chaijiegan0107
authored andcommitted
FROMLIST: coresight: Add coresight TGU driver
Add driver to support Coresight device TGU (Trigger Generation Unit). TGU is a Data Engine which can be utilized to sense a plurality of signals and create a trigger into the CTI or generate interrupts to processors. Add probe/enable/disable functions for tgu. Link: https://lore.kernel.org/all/20250423-tgu_patch-v5-2-3b52c105cc63@quicinc.com/ Signed-off-by: Songwei Chai <quic_songchai@quicinc.com>
1 parent 0dd7339 commit 4bba4b9

5 files changed

Lines changed: 271 additions & 0 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
What: /sys/bus/coresight/devices/<tgu-name>/enable_tgu
2+
Date: February 2025
3+
KernelVersion 6.15
4+
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Sam Chai (QUIC) <quic_songchai@quicinc.com>
5+
Description:
6+
(RW) Set/Get the enable/disable status of TGU
7+
Accepts only one of the 2 values - 0 or 1.
8+
0 : disable TGU.
9+
1 : enable TGU.

drivers/hwtracing/coresight/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,4 +291,15 @@ config CORESIGHT_REMOTE_ETM
291291
To compile this driver as a module, choose M here: the module will be
292292
called coresight-remote-etm.
293293

294+
config CORESIGHT_TGU
295+
tristate "CoreSight Trigger Generation Unit driver"
296+
help
297+
This driver provides support for Trigger Generation Unit that is
298+
used to detect patterns or sequences on a given set of signals.
299+
TGU is used to monitor a particular bus within a given region to
300+
detect illegal transaction sequences or slave responses. It is also
301+
used to monitor a data stream to detect protocol violations and to
302+
provide a trigger point for centering data around a specific event
303+
within the trace data buffer.
304+
294305
endif

drivers/hwtracing/coresight/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
5555
obj-$(CONFIG_CORESIGHT_QMI) += coresight-qmi.o
5656
obj-$(CONFIG_CORESIGHT_REMOTE_ETM) += coresight-remote-etm.o
5757
obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
58+
obj-$(CONFIG_CORESIGHT_TGU) += coresight-tgu.o
5859
obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
5960
coresight-ctcu-y := coresight-ctcu-core.o
6061
obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
4+
*/
5+
6+
#include <linux/amba/bus.h>
7+
#include <linux/coresight.h>
8+
#include <linux/device.h>
9+
#include <linux/err.h>
10+
#include <linux/io.h>
11+
#include <linux/kernel.h>
12+
#include <linux/module.h>
13+
#include <linux/of.h>
14+
15+
#include "coresight-priv.h"
16+
#include "coresight-tgu.h"
17+
18+
DEFINE_CORESIGHT_DEVLIST(tgu_devs, "tgu");
19+
20+
static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata)
21+
{
22+
CS_UNLOCK(drvdata->base);
23+
/* Enable TGU to program the triggers */
24+
tgu_writel(drvdata, 1, TGU_CONTROL);
25+
CS_LOCK(drvdata->base);
26+
}
27+
28+
static int tgu_enable(struct coresight_device *csdev, enum cs_mode mode,
29+
void *data)
30+
{
31+
struct tgu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
32+
33+
spin_lock(&drvdata->spinlock);
34+
35+
if (drvdata->enable) {
36+
spin_unlock(&drvdata->spinlock);
37+
return -EBUSY;
38+
}
39+
tgu_write_all_hw_regs(drvdata);
40+
drvdata->enable = true;
41+
42+
spin_unlock(&drvdata->spinlock);
43+
return 0;
44+
}
45+
46+
static int tgu_disable(struct coresight_device *csdev, void *data)
47+
{
48+
struct tgu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
49+
50+
spin_lock(&drvdata->spinlock);
51+
if (drvdata->enable) {
52+
CS_UNLOCK(drvdata->base);
53+
tgu_writel(drvdata, 0, TGU_CONTROL);
54+
CS_LOCK(drvdata->base);
55+
56+
drvdata->enable = false;
57+
}
58+
spin_unlock(&drvdata->spinlock);
59+
return 0;
60+
}
61+
62+
static ssize_t enable_tgu_show(struct device *dev,
63+
struct device_attribute *attr, char *buf)
64+
{
65+
bool enabled;
66+
67+
struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
68+
69+
spin_lock(&drvdata->spinlock);
70+
enabled = drvdata->enable;
71+
spin_unlock(&drvdata->spinlock);
72+
73+
return sysfs_emit(buf, "%d\n", enabled);
74+
}
75+
76+
/* enable_tgu_store - Configure Trace and Gating Unit (TGU) triggers. */
77+
static ssize_t enable_tgu_store(struct device *dev,
78+
struct device_attribute *attr, const char *buf,
79+
size_t size)
80+
{
81+
int ret = 0;
82+
unsigned long val;
83+
struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
84+
85+
ret = kstrtoul(buf, 0, &val);
86+
if (ret)
87+
return ret;
88+
89+
if (val) {
90+
ret = pm_runtime_resume_and_get(dev->parent);
91+
if (ret)
92+
return ret;
93+
ret = tgu_enable(drvdata->csdev, CS_MODE_SYSFS, NULL);
94+
if (ret)
95+
pm_runtime_put(dev->parent);
96+
} else {
97+
ret = tgu_disable(drvdata->csdev, NULL);
98+
pm_runtime_put(dev->parent);
99+
}
100+
101+
if (ret)
102+
return ret;
103+
return size;
104+
}
105+
static DEVICE_ATTR_RW(enable_tgu);
106+
107+
static const struct coresight_ops_helper tgu_helper_ops = {
108+
.enable = tgu_enable,
109+
.disable = tgu_disable,
110+
};
111+
112+
static const struct coresight_ops tgu_ops = {
113+
.helper_ops = &tgu_helper_ops,
114+
};
115+
116+
static struct attribute *tgu_common_attrs[] = {
117+
&dev_attr_enable_tgu.attr,
118+
NULL,
119+
};
120+
121+
static const struct attribute_group tgu_common_grp = {
122+
.attrs = tgu_common_attrs,
123+
{ NULL },
124+
};
125+
126+
static const struct attribute_group *tgu_attr_groups[] = {
127+
&tgu_common_grp,
128+
NULL,
129+
};
130+
131+
static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
132+
{
133+
int ret = 0;
134+
struct device *dev = &adev->dev;
135+
struct coresight_desc desc = { 0 };
136+
struct coresight_platform_data *pdata;
137+
struct tgu_drvdata *drvdata;
138+
139+
desc.name = coresight_alloc_device_name(&tgu_devs, dev);
140+
if (!desc.name)
141+
return -ENOMEM;
142+
143+
pdata = coresight_get_platform_data(dev);
144+
if (IS_ERR(pdata))
145+
return PTR_ERR(pdata);
146+
147+
adev->dev.platform_data = pdata;
148+
149+
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
150+
if (!drvdata)
151+
return -ENOMEM;
152+
153+
drvdata->dev = &adev->dev;
154+
dev_set_drvdata(dev, drvdata);
155+
156+
drvdata->base = devm_ioremap_resource(dev, &adev->res);
157+
if (!drvdata->base)
158+
return -ENOMEM;
159+
160+
spin_lock_init(&drvdata->spinlock);
161+
162+
drvdata->enable = false;
163+
desc.type = CORESIGHT_DEV_TYPE_HELPER;
164+
desc.pdata = adev->dev.platform_data;
165+
desc.dev = &adev->dev;
166+
desc.ops = &tgu_ops;
167+
desc.groups = tgu_attr_groups;
168+
169+
drvdata->csdev = coresight_register(&desc);
170+
if (IS_ERR(drvdata->csdev)) {
171+
ret = PTR_ERR(drvdata->csdev);
172+
goto err;
173+
}
174+
175+
pm_runtime_put(&adev->dev);
176+
return 0;
177+
err:
178+
pm_runtime_put(&adev->dev);
179+
return ret;
180+
}
181+
182+
static void tgu_remove(struct amba_device *adev)
183+
{
184+
struct tgu_drvdata *drvdata = dev_get_drvdata(&adev->dev);
185+
186+
coresight_unregister(drvdata->csdev);
187+
}
188+
189+
static const struct amba_id tgu_ids[] = {
190+
{
191+
.id = 0x000f0e00,
192+
.mask = 0x000fffff,
193+
.data = "TGU",
194+
},
195+
{ 0, 0, NULL },
196+
};
197+
198+
MODULE_DEVICE_TABLE(amba, tgu_ids);
199+
200+
static struct amba_driver tgu_driver = {
201+
.drv = {
202+
.name = "coresight-tgu",
203+
.suppress_bind_attrs = true,
204+
},
205+
.probe = tgu_probe,
206+
.remove = tgu_remove,
207+
.id_table = tgu_ids,
208+
};
209+
210+
module_amba_driver(tgu_driver);
211+
212+
MODULE_LICENSE("GPL");
213+
MODULE_DESCRIPTION("CoreSight TGU driver");
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
4+
*/
5+
6+
#ifndef _CORESIGHT_TGU_H
7+
#define _CORESIGHT_TGU_H
8+
9+
/* Register addresses */
10+
#define TGU_CONTROL 0x0000
11+
12+
/* Register read/write */
13+
#define tgu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
14+
#define tgu_readl(drvdata, off) __raw_readl(drvdata->base + off)
15+
16+
/**
17+
* struct tgu_drvdata - Data structure for a TGU (Trigger Generator Unit)
18+
* @base: Memory-mapped base address of the TGU device
19+
* @dev: Pointer to the associated device structure
20+
* @csdev: Pointer to the associated coresight device
21+
* @spinlock: Spinlock for handling concurrent access
22+
* @enable: Flag indicating whether the TGU device is enabled
23+
*
24+
* This structure defines the data associated with a TGU device,
25+
* including its base address, device pointers, clock, spinlock for
26+
* synchronization, trigger data pointers, maximum limits for various
27+
* trigger-related parameters, and enable status.
28+
*/
29+
struct tgu_drvdata {
30+
void __iomem *base;
31+
struct device *dev;
32+
struct coresight_device *csdev;
33+
spinlock_t spinlock;
34+
bool enable;
35+
};
36+
37+
#endif

0 commit comments

Comments
 (0)