On 09/01/2026 02:11, Songwei Chai wrote:
Add driver to support 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.
Signed-off-by: Songwei Chai songwei.chai@oss.qualcomm.com
.../ABI/testing/sysfs-bus-amba-devices-tgu | 9 + drivers/Makefile | 1 + drivers/hwtracing/Kconfig | 2 + drivers/hwtracing/qcom/Kconfig | 18 ++ drivers/hwtracing/qcom/Makefile | 3 + drivers/hwtracing/qcom/tgu.c | 176 ++++++++++++++++++ drivers/hwtracing/qcom/tgu.h | 51 +++++ 7 files changed, 260 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-amba-devices-tgu create mode 100644 drivers/hwtracing/qcom/Kconfig create mode 100644 drivers/hwtracing/qcom/Makefile create mode 100644 drivers/hwtracing/qcom/tgu.c create mode 100644 drivers/hwtracing/qcom/tgu.h
diff --git a/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu new file mode 100644 index 000000000000..56ec3f5ab5d6 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-amba-devices-tgu @@ -0,0 +1,9 @@ +What: /sys/bus/amba/devices/<tgu-name>/enable_tgu +Date: January 2026 +KernelVersion 6.19
It's a bit too late for v6.19, this should rather be 6.20/7.0
Suzuki
+Contact: Jinlong Mao jinlong.mao@oss.qualcomm.com, Songwei Chai songwei.chai@oss.qualcomm.com +Description:
(RW) Set/Get the enable/disable status of TGUAccepts only one of the 2 values - 0 or 1.0 : disable TGU.1 : enable TGU.diff --git a/drivers/Makefile b/drivers/Makefile index ccc05f1eae3e..9608a3debb1f 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -177,6 +177,7 @@ obj-$(CONFIG_RAS) += ras/ obj-$(CONFIG_USB4) += thunderbolt/ obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/ obj-y += hwtracing/intel_th/ +obj-y += hwtracing/qcom/ obj-$(CONFIG_STM) += hwtracing/stm/ obj-$(CONFIG_HISI_PTT) += hwtracing/ptt/ obj-y += android/ diff --git a/drivers/hwtracing/Kconfig b/drivers/hwtracing/Kconfig index 911ee977103c..8a640218eed8 100644 --- a/drivers/hwtracing/Kconfig +++ b/drivers/hwtracing/Kconfig @@ -7,4 +7,6 @@ source "drivers/hwtracing/intel_th/Kconfig" source "drivers/hwtracing/ptt/Kconfig" +source "drivers/hwtracing/qcom/Kconfig"
- endmenu
diff --git a/drivers/hwtracing/qcom/Kconfig b/drivers/hwtracing/qcom/Kconfig new file mode 100644 index 000000000000..d6f6d4b0f28e --- /dev/null +++ b/drivers/hwtracing/qcom/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# QCOM specific hwtracing drivers +# +menu "Qualcomm specific hwtracing drivers"
+config QCOM_TGU
- tristate "QCOM Trigger Generation Unit driver"
- help
This driver provides support for Trigger Generation Unit that isused to detect patterns or sequences on a given set of signals.TGU is used to monitor a particular bus within a given region todetect illegal transaction sequences or slave responses. It is alsoused to monitor a data stream to detect protocol violations and toprovide a trigger point for centering data around a specific eventwithin the trace data buffer.+endmenu diff --git a/drivers/hwtracing/qcom/Makefile b/drivers/hwtracing/qcom/Makefile new file mode 100644 index 000000000000..5a0a868c1ea0 --- /dev/null +++ b/drivers/hwtracing/qcom/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_QCOM_TGU) += tgu.o diff --git a/drivers/hwtracing/qcom/tgu.c b/drivers/hwtracing/qcom/tgu.c new file mode 100644 index 000000000000..c5b2b384e6ae --- /dev/null +++ b/drivers/hwtracing/qcom/tgu.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
- */
+#include <linux/amba/bus.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/pm_runtime.h>
+#include "tgu.h"
+static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata) +{
- TGU_UNLOCK(drvdata->base);
- /* Enable TGU to program the triggers */
- writel(1, drvdata->base + TGU_CONTROL);
- TGU_LOCK(drvdata->base);
+}
+static int tgu_enable(struct device *dev) +{
- struct tgu_drvdata *drvdata = dev_get_drvdata(dev);
- guard(spinlock)(&drvdata->lock);
- if (drvdata->enable)
return -EBUSY;- tgu_write_all_hw_regs(drvdata);
- drvdata->enable = true;
- return 0;
+}
+static void tgu_disable(struct device *dev) +{
- struct tgu_drvdata *drvdata = dev_get_drvdata(dev);
- guard(spinlock)(&drvdata->lock);
- if (drvdata->enable) {
TGU_UNLOCK(drvdata->base);writel(0, drvdata->base + TGU_CONTROL);TGU_LOCK(drvdata->base);drvdata->enable = false;- }
+}
+static ssize_t enable_tgu_show(struct device *dev,
struct device_attribute *attr, char *buf)+{
- struct tgu_drvdata *drvdata = dev_get_drvdata(dev);
- bool enabled;
- guard(spinlock)(&drvdata->lock);
- enabled = drvdata->enable;
- return sysfs_emit(buf, "%d\n", enabled ? 1 : 0);
+}
+/* enable_tgu_store - Configure Trace and Gating Unit (TGU) triggers. */ +static ssize_t enable_tgu_store(struct device *dev,
struct device_attribute *attr,const char *buf,size_t size)+{
- unsigned long val;
- int ret = 0;
- ret = kstrtoul(buf, 0, &val);
- if (ret)
return ret;- if (val) {
ret = pm_runtime_resume_and_get(dev);if (ret)return ret;ret = tgu_enable(dev);if (ret) {pm_runtime_put(dev);return ret;}- } else {
tgu_disable(dev);pm_runtime_put(dev);- }
- return size;
+} +static DEVICE_ATTR_RW(enable_tgu);
+static struct attribute *tgu_common_attrs[] = {
- &dev_attr_enable_tgu.attr,
- NULL,
+};
+static const struct attribute_group tgu_common_grp = {
- .attrs = tgu_common_attrs,
- NULL,
+};
+static const struct attribute_group *tgu_attr_groups[] = {
- &tgu_common_grp,
- NULL,
+};
+static int tgu_probe(struct amba_device *adev, const struct amba_id *id) +{
- struct device *dev = &adev->dev;
- struct tgu_drvdata *drvdata;
- int ret;
- 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 (IS_ERR(drvdata->base))
return PTR_ERR(drvdata->base);- spin_lock_init(&drvdata->lock);
- ret = sysfs_create_groups(&dev->kobj, tgu_attr_groups);
- if (ret) {
dev_err(dev, "failed to create sysfs groups: %d\n", ret);return ret;- }
- drvdata->enable = false;
- pm_runtime_put(&adev->dev);
- return 0;
+}
+static void tgu_remove(struct amba_device *adev) +{
- struct device *dev = &adev->dev;
- sysfs_remove_groups(&dev->kobj, tgu_attr_groups);
- tgu_disable(dev);
+}
+static const struct amba_id tgu_ids[] = {
- {
.id = 0x000f0e00,.mask = 0x000fffff,- },
- { 0, 0, NULL },
+};
+MODULE_DEVICE_TABLE(amba, tgu_ids);
+static struct amba_driver tgu_driver = {
- .drv = {
.name = "qcom-tgu",.suppress_bind_attrs = true,- },
- .probe = tgu_probe,
- .remove = tgu_remove,
- .id_table = tgu_ids,
+};
+module_amba_driver(tgu_driver);
+MODULE_AUTHOR("Songwei Chai songwei.chai@oss.qualcomm.com"); +MODULE_AUTHOR("Jinlong Mao jinlong.mao@oss.qualcomm.com"); +MODULE_DESCRIPTION("Qualcomm Trigger Generation Unit driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwtracing/qcom/tgu.h b/drivers/hwtracing/qcom/tgu.h new file mode 100644 index 000000000000..b11cfb28261d --- /dev/null +++ b/drivers/hwtracing/qcom/tgu.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/*
- Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
- */
+#ifndef _QCOM_TGU_H +#define _QCOM_TGU_H
+/* Register addresses */ +#define TGU_CONTROL 0x0000 +#define TGU_LAR 0xfb0 +#define TGU_UNLOCK_OFFSET 0xc5acce55
+static inline void TGU_LOCK(void __iomem *addr) +{
- do {
/* Wait for things to settle */mb();writel_relaxed(0x0, addr + TGU_LAR);- } while (0);
+}
+static inline void TGU_UNLOCK(void __iomem *addr) +{
- do {
writel_relaxed(TGU_UNLOCK_OFFSET, addr + TGU_LAR);/* Make sure everyone has seen this */mb();- } while (0);
+}
+/**
- struct tgu_drvdata - Data structure for a TGU (Trigger Generator Unit)
- @base: Memory-mapped base address of the TGU device
- @dev: Pointer to the associated device structure
- @lock: Spinlock for handling concurrent access
- @enable: Flag indicating whether the TGU device is enabled
- This structure defines the data associated with a TGU device,
- including its base address, device pointers, clock, spinlock for
- synchronization, trigger data pointers, maximum limits for various
- trigger-related parameters, and enable status.
- */
+struct tgu_drvdata {
- void __iomem *base;
- struct device *dev;
- spinlock_t lock;
- bool enable;
+};
+#endif