From: Zane Leung <liangzhen@linux.spacemit.com>
To: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
palmer@dabbelt.com, pjw@kernel.org, gregkh@linuxfoundation.org,
alexander.shishkin@linux.intel.com, irogers@google.com
Cc: coresight@lists.linaro.org, peterz@infradead.org,
mingo@redhat.com, namhyung@kernel.org, mark.rutland@arm.com,
jolsa@kernel.org, adrian.hunter@intel.com,
kan.liang@linux.intel.com, mchitale@gmail.com,
anup@brainfault.org, atish.patra@linux.dev,
andrew.jones@oss.qualcomm.com, sunilvl@oss.qualcomm.com,
linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org,
anup.patel@oss.qualcomm.com, mayuresh.chitale@oss.qualcomm.com,
zhuangqiubin@linux.spacemit.com
Subject: [RFC PATCH 04/12] coresight: Add RISC-V Trace Funnel driver
Date: Tue, 14 Apr 2026 11:41:45 +0800 [thread overview]
Message-ID: <20260414034153.3272485-5-liangzhen@linux.spacemit.com> (raw)
In-Reply-To: <20260414034153.3272485-1-liangzhen@linux.spacemit.com>
From: liangzhen <zhen.liang@spacemit.com>
Add initial implementation of RISC-V trace funnel
driver. The funnel is defined in the RISC-V Trace
Control Interface specification.
Signed-off-by: liangzhen <zhen.liang@spacemit.com>
---
drivers/hwtracing/coresight/Kconfig | 12 +
drivers/hwtracing/coresight/Makefile | 1 +
drivers/hwtracing/coresight/rvtrace-funnel.c | 244 +++++++++++++++++++
drivers/hwtracing/coresight/rvtrace-funnel.h | 31 +++
4 files changed, 288 insertions(+)
create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.c
create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.h
diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index 3e46728f2482..8381a84e2699 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -288,9 +288,21 @@ config RVTRACE
dynamically aggregated with CoreSight trace infrastructure
at run time to form a complete trace path.
+config RVTRACE_FUNNEL
+ tristate "RISCV Trace Funnel driver"
+ depends on RVTRACE
+ help
+ his driver provides support for the Trace Funnel driver. The Funnel
+ aggregates the trace from each of its inputs and sends the combined
+ trace stream to its designated Trace Sink or ATB Bridge.
+
+ To compile this driver as a module, choose M here: the module
+ will be called rvtrace-funnel.
+
config RVTRACE_ENCODER
tristate "RISCV Trace Encoder driver"
depends on RVTRACE
+ select RVTRACE_FUNNEL
help
This driver provides support for the Trace Encoder module, tracing
the instructions that a processor is executing. This is primarily
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 9a526b1fb95a..409a0abf0642 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -59,5 +59,6 @@ coresight-ctcu-y := coresight-ctcu-core.o
obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
obj-$(CONFIG_RVTRACE) += rvtrace.o
rvtrace-y := rvtrace-core.o
+obj-$(CONFIG_RVTRACE_FUNNEL) += rvtrace-funnel.o
obj-$(CONFIG_RVTRACE_ENCODER) += rvtrace-encoder.o
rvtrace-encoder-y := rvtrace-encoder-core.o rvtrace-encoder-sysfs.o
diff --git a/drivers/hwtracing/coresight/rvtrace-funnel.c b/drivers/hwtracing/coresight/rvtrace-funnel.c
new file mode 100644
index 000000000000..0dc7799a64ac
--- /dev/null
+++ b/drivers/hwtracing/coresight/rvtrace-funnel.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(C) 2026 Spacemit Limited. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/coresight.h>
+#include <linux/platform_device.h>
+#include <linux/rvtrace.h>
+
+#include "coresight-priv.h"
+#include "rvtrace-funnel.h"
+
+DEFINE_CORESIGHT_DEVLIST(funnel_devs, "rvtrace_funnel");
+
+static int funnel_enable_hw(struct rvtrace_component *comp, int port)
+{
+ u32 disinput;
+ int ret = 0;
+ struct funnel_data *funnel_data = rvtrace_component_data(comp);
+
+ if (!comp->was_reset) {
+ ret = rvtrace_component_reset(comp);
+ if (ret)
+ goto done;
+ }
+
+ disinput = readl_relaxed(comp->base + RVTRACE_FUNNEL_DISINPUT_OFFSET);
+ disinput &= ~(1 << port);
+ writel_relaxed(disinput, comp->base + RVTRACE_FUNNEL_DISINPUT_OFFSET);
+ ret = rvtrace_poll_bit(comp, RVTRACE_FUNNEL_DISINPUT_OFFSET, port, 0);
+ if (ret)
+ goto done;
+
+ if (!funnel_data->was_enabled) {
+ ret = rvtrace_enable_component(comp);
+ if (ret)
+ goto done;
+ }
+
+done:
+ return ret;
+}
+
+static int funnel_enable(struct coresight_device *csdev,
+ struct coresight_connection *in,
+ struct coresight_connection *out)
+{
+ int ret = 0;
+ struct rvtrace_component *comp = dev_get_drvdata(csdev->dev.parent);
+ struct funnel_data *funnel_data = rvtrace_component_data(comp);
+ unsigned long flags;
+ bool first_enable = false;
+
+ spin_lock_irqsave(&funnel_data->spinlock, flags);
+ if (in->dest_refcnt == 0) {
+ ret = funnel_enable_hw(comp, in->dest_port);
+ if (!ret)
+ first_enable = true;
+ }
+ if (!ret) {
+ in->dest_refcnt++;
+ funnel_data->input_refcnt++;
+ }
+
+ if (first_enable)
+ dev_dbg(&csdev->dev, "Trace funnel inport %d enabled\n",
+ in->dest_port);
+
+ spin_unlock_irqrestore(&funnel_data->spinlock, flags);
+
+ return ret;
+}
+
+static void funnel_disable_hw(struct rvtrace_component *comp, int inport)
+{
+ struct funnel_data *funnel_data = rvtrace_component_data(comp);
+
+ if (--funnel_data->input_refcnt != 0)
+ return;
+
+ writel_relaxed(RVTRACE_FUNNEL_DISINPUT_MASK, comp->base + RVTRACE_FUNNEL_DISINPUT_OFFSET);
+
+ if (rvtrace_disable_component(comp))
+ dev_err(&funnel_data->csdev->dev,
+ "timeout while waiting for Trace Funnel to be disabled\n");
+
+ if (rvtrace_comp_is_empty(comp))
+ dev_err(&funnel_data->csdev->dev,
+ "timeout while waiting for Trace Funnel internal buffers become empty\n");
+}
+
+static void funnel_disable(struct coresight_device *csdev,
+ struct coresight_connection *in,
+ struct coresight_connection *out)
+{
+ struct rvtrace_component *comp = dev_get_drvdata(csdev->dev.parent);
+ struct funnel_data *funnel_data = rvtrace_component_data(comp);
+ unsigned long flags;
+ bool last_disable = false;
+
+ spin_lock_irqsave(&funnel_data->spinlock, flags);
+ if (--in->dest_refcnt == 0) {
+ funnel_disable_hw(comp, in->dest_port);
+ last_disable = true;
+ }
+ spin_unlock_irqrestore(&funnel_data->spinlock, flags);
+
+ if (last_disable)
+ dev_dbg(&csdev->dev, "Trace funnel inport %d disabled\n",
+ in->dest_port);
+
+ if (funnel_data->input_refcnt == 0)
+ dev_dbg(&csdev->dev, "Trace funnel disabled\n");
+}
+
+static const struct coresight_ops_link funnel_link_ops = {
+ .enable = funnel_enable,
+ .disable = funnel_disable,
+};
+
+static const struct coresight_ops funnel_cs_ops = {
+ .link_ops = &funnel_link_ops,
+};
+
+static ssize_t reset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+ struct rvtrace_component *comp = dev_get_drvdata(dev->parent);
+ struct funnel_data *funnel_data = rvtrace_component_data(comp);
+ unsigned long flags;
+
+ if (kstrtoul(buf, 16, &val))
+ return -EINVAL;
+
+ spin_lock_irqsave(&funnel_data->spinlock, flags);
+
+ if (val) {
+ if (rvtrace_component_reset(comp)) {
+ comp->was_reset = false;
+ spin_unlock_irqrestore(&funnel_data->spinlock, flags);
+ return -EINVAL;
+ }
+ }
+
+ spin_unlock_irqrestore(&funnel_data->spinlock, flags);
+
+ return size;
+}
+static DEVICE_ATTR_WO(reset);
+
+static ssize_t cpu_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val;
+ struct rvtrace_component *comp = dev_get_drvdata(dev->parent);
+
+ val = comp->cpu;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(cpu);
+
+static struct attribute *trace_funnel_attrs[] = {
+ coresight_simple_reg32(control, RVTRACE_COMPONENT_CTRL_OFFSET),
+ coresight_simple_reg32(impl, RVTRACE_COMPONENT_IMPL_OFFSET),
+ coresight_simple_reg32(disinput, RVTRACE_FUNNEL_DISINPUT_OFFSET),
+ &dev_attr_reset.attr,
+ &dev_attr_cpu.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(trace_funnel);
+
+static int funnel_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct funnel_data *funnel_data;
+ struct rvtrace_component *comp;
+ struct coresight_desc desc = { 0 };
+
+ comp = rvtrace_register_component(pdev);
+ if (IS_ERR(comp))
+ return PTR_ERR(comp);
+
+ funnel_data = devm_kzalloc(dev, sizeof(*funnel_data), GFP_KERNEL);
+ if (!funnel_data)
+ return -ENOMEM;
+
+ spin_lock_init(&funnel_data->spinlock);
+
+ pdata = coresight_get_platform_data(dev);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
+
+ platform_set_drvdata(pdev, comp);
+
+ desc.name = coresight_alloc_device_name(&funnel_devs, dev);
+ desc.access = CSDEV_ACCESS_IOMEM(comp->base);
+ desc.type = CORESIGHT_DEV_TYPE_LINK;
+ desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
+ desc.ops = &funnel_cs_ops;
+ desc.pdata = pdata;
+ desc.dev = dev;
+ desc.groups = trace_funnel_groups;
+ funnel_data->csdev = coresight_register(&desc);
+ if (IS_ERR(funnel_data->csdev))
+ return PTR_ERR(funnel_data->csdev);
+
+ comp->id.data = funnel_data;
+
+ dev_dbg(dev, "Trace Funnel initialized\n");
+
+ return 0;
+}
+
+static void funnel_remove(struct platform_device *pdev)
+{
+ struct rvtrace_component *comp = platform_get_drvdata(pdev);
+ struct funnel_data *funnel_data = rvtrace_component_data(comp);
+
+ coresight_unregister(funnel_data->csdev);
+}
+
+static const struct of_device_id funnel_match[] = {
+ {.compatible = "riscv,trace-funnel"},
+ {},
+};
+
+static struct platform_driver funnel_driver = {
+ .probe = funnel_probe,
+ .remove = funnel_remove,
+ .driver = {
+ .name = "trace-funnel",
+ .of_match_table = funnel_match,
+ },
+};
+
+module_platform_driver(funnel_driver);
+
+MODULE_DESCRIPTION("RISC-V Trace funnel driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwtracing/coresight/rvtrace-funnel.h b/drivers/hwtracing/coresight/rvtrace-funnel.h
new file mode 100644
index 000000000000..e5247e6c1bf5
--- /dev/null
+++ b/drivers/hwtracing/coresight/rvtrace-funnel.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright(C) 2026 Spacemit Limited. All rights reserved.
+ */
+
+#ifndef _RVTRACE_FUNNEL_H
+#define _RVTRACE_FUNNEL_H
+
+#include <linux/spinlock.h>
+#include <linux/coresight.h>
+
+/* Disable Individual Funnel Inputs */
+#define RVTRACE_FUNNEL_DISINPUT_OFFSET 0x008
+#define RVTRACE_FUNNEL_DISINPUT_MASK 0xffff
+
+/**
+ * struct funnel_data - specifics associated to a Trace Funnel component
+ * @csdev: Component vitals needed by the framework.
+ * @spinlock: Only one at a time pls.
+ * @was_enabled: Flag showing whether the Trace Funnel was enabled.
+ * @input_refcnt: Record the number of funnel inputs
+ */
+struct funnel_data {
+ struct coresight_device *csdev;
+ spinlock_t spinlock;
+ bool was_enabled;
+ u32 input_refcnt;
+ u32 disintput;
+};
+
+#endif
--
2.34.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2026-04-14 3:43 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-14 3:41 [RFC PATCH 00/12] Add Linux RISC-V trace support via CoreSight Zane Leung
2026-04-14 3:41 ` [RFC PATCH 01/12] coresight: Add RISC-V support to CoreSight tracing Zane Leung
2026-04-14 3:41 ` [RFC PATCH 02/12] coresight: Initial implementation of RISC-V trace driver Zane Leung
2026-04-14 3:41 ` [RFC PATCH 03/12] coresight: Add RISC-V Trace Encoder driver Zane Leung
2026-04-14 3:41 ` Zane Leung [this message]
2026-04-14 3:41 ` [RFC PATCH 05/12] coresight: Add RISC-V Trace ATB Bridge driver Zane Leung
2026-04-14 3:41 ` [RFC PATCH 06/12] coresight rvtrace: Add timestamp component support for encoder and funnel Zane Leung
2026-04-14 3:41 ` [RFC PATCH 07/12] coresight: Add RISC-V PMU name support Zane Leung
2026-04-14 3:41 ` [RFC PATCH 08/12] perf tools: riscv: making rvtrace PMU listable Zane Leung
2026-04-14 3:41 ` [RFC PATCH 09/12] perf tools: Add RISC-V trace PMU record capabilities Zane Leung
2026-04-14 23:31 ` Bo Gan
2026-04-14 3:41 ` [RFC PATCH 10/12] perf tools: Add Nexus RISC-V Trace decoder Zane Leung
2026-04-14 3:41 ` [RFC PATCH 11/12] perf symbols: Add RISC-V PLT entry sizes Zane Leung
2026-04-14 3:41 ` [RFC PATCH 12/12] perf tools: Integrate RISC-V trace decoder into auxtrace Zane Leung
2026-04-14 4:15 ` [RFC PATCH 00/12] Add Linux RISC-V trace support via CoreSight Jie Gan
2026-04-14 8:08 ` Zane Leung
2026-04-14 7:23 ` Anup Patel
2026-04-14 9:04 ` Zane Leung
2026-04-15 0:10 ` Bo Gan
2026-04-15 1:23 ` Zane Leung
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260414034153.3272485-5-liangzhen@linux.spacemit.com \
--to=liangzhen@linux.spacemit.com \
--cc=adrian.hunter@intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=andrew.jones@oss.qualcomm.com \
--cc=anup.patel@oss.qualcomm.com \
--cc=anup@brainfault.org \
--cc=atish.patra@linux.dev \
--cc=conor+dt@kernel.org \
--cc=coresight@lists.linaro.org \
--cc=gregkh@linuxfoundation.org \
--cc=irogers@google.com \
--cc=jolsa@kernel.org \
--cc=kan.liang@linux.intel.com \
--cc=krzk+dt@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=mark.rutland@arm.com \
--cc=mayuresh.chitale@oss.qualcomm.com \
--cc=mchitale@gmail.com \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=palmer@dabbelt.com \
--cc=peterz@infradead.org \
--cc=pjw@kernel.org \
--cc=robh@kernel.org \
--cc=sunilvl@oss.qualcomm.com \
--cc=zhuangqiubin@linux.spacemit.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox