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 02/12] coresight: Initial implementation of RISC-V trace driver
Date: Tue, 14 Apr 2026 11:41:43 +0800 [thread overview]
Message-ID: <20260414034153.3272485-3-liangzhen@linux.spacemit.com> (raw)
In-Reply-To: <20260414034153.3272485-1-liangzhen@linux.spacemit.com>
From: liangzhen <zhen.liang@spacemit.com>
Implement some common driver interfaces RISC-V trace
where RISC-V trace components are instantiated by a
common platform driver and a separate RISC-V trace
driver for each type of RISC-V trace component.
Signed-off-by: liangzhen <zhen.liang@spacemit.com>
---
drivers/hwtracing/coresight/Kconfig | 8 ++
drivers/hwtracing/coresight/Makefile | 2 +
drivers/hwtracing/coresight/rvtrace-core.c | 135 +++++++++++++++++++++
include/linux/rvtrace.h | 116 ++++++++++++++++++
4 files changed, 261 insertions(+)
create mode 100644 drivers/hwtracing/coresight/rvtrace-core.c
create mode 100644 include/linux/rvtrace.h
diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index 2b1ebe3f614d..5adeaf78a080 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -280,4 +280,12 @@ config CORESIGHT_TNOC
To compile this driver as a module, choose M here: the module will be
called coresight-tnoc.
+config RVTRACE
+ bool "RISC-V Trace Support"
+ help
+ This enables support for the RISC-V trace drivers. drivers
+ (including Trace Encoder, Trace Funnel and ATB Bridge) are
+ dynamically aggregated with CoreSight trace infrastructure
+ at run time to form a complete trace path.
+
endif
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index ab16d06783a5..c21a9e25e148 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -57,3 +57,5 @@ obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
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
diff --git a/drivers/hwtracing/coresight/rvtrace-core.c b/drivers/hwtracing/coresight/rvtrace-core.c
new file mode 100644
index 000000000000..c74f43869d8b
--- /dev/null
+++ b/drivers/hwtracing/coresight/rvtrace-core.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(C) 2026 Spacemit Limited. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/percpu.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/rvtrace.h>
+
+int rvtrace_poll_bit(struct rvtrace_component *comp, int offset,
+ int bit, int bitval)
+{
+ int i = RVTRACE_TIMEOUT_US;
+ u32 val;
+
+ while (i--) {
+ val = readl_relaxed(comp->base + offset);
+ if (((val >> bit) & 0x1) == bitval)
+ break;
+ udelay(1);
+ }
+
+ return (i < 0) ? -ETIMEDOUT : 0;
+}
+EXPORT_SYMBOL_GPL(rvtrace_poll_bit);
+
+int rvtrace_enable_component(struct rvtrace_component *comp)
+{
+ u32 val;
+
+ val = readl_relaxed(comp->base + RVTRACE_COMPONENT_CTRL_OFFSET);
+ val |= BIT(RVTRACE_COMPONENT_CTRL_ENABLE_SHIFT);
+ writel_relaxed(val, comp->base + RVTRACE_COMPONENT_CTRL_OFFSET);
+ return rvtrace_poll_bit(comp, RVTRACE_COMPONENT_CTRL_OFFSET,
+ RVTRACE_COMPONENT_CTRL_ENABLE_SHIFT, 1);
+}
+EXPORT_SYMBOL_GPL(rvtrace_enable_component);
+
+int rvtrace_disable_component(struct rvtrace_component *comp)
+{
+ u32 val;
+
+ val = readl_relaxed(comp->base + RVTRACE_COMPONENT_CTRL_OFFSET);
+ val &= ~BIT(RVTRACE_COMPONENT_CTRL_ENABLE_SHIFT);
+ writel_relaxed(val, comp->base + RVTRACE_COMPONENT_CTRL_OFFSET);
+ return rvtrace_poll_bit(comp, RVTRACE_COMPONENT_CTRL_OFFSET,
+ RVTRACE_COMPONENT_CTRL_ENABLE_SHIFT, 0);
+}
+EXPORT_SYMBOL_GPL(rvtrace_disable_component);
+
+int rvtrace_component_reset(struct rvtrace_component *comp)
+{
+ int ret;
+
+ writel_relaxed(0, comp->base + RVTRACE_COMPONENT_CTRL_OFFSET);
+ ret = rvtrace_poll_bit(comp, RVTRACE_COMPONENT_CTRL_OFFSET,
+ RVTRACE_COMPONENT_CTRL_ACTIVE_SHIFT, 0);
+ if (ret)
+ return ret;
+
+ writel_relaxed(RVTRACE_COMPONENT_CTRL_ACTIVE_MASK,
+ comp->base + RVTRACE_COMPONENT_CTRL_OFFSET);
+ return rvtrace_poll_bit(comp, RVTRACE_COMPONENT_CTRL_OFFSET,
+ RVTRACE_COMPONENT_CTRL_ACTIVE_SHIFT, 1);
+}
+EXPORT_SYMBOL_GPL(rvtrace_component_reset);
+
+struct rvtrace_component *rvtrace_register_component(struct platform_device *pdev)
+{
+ int ret;
+ void __iomem *base;
+ struct device *dev = &pdev->dev;
+ struct rvtrace_component *comp;
+ struct resource *res;
+ struct device_node *node;
+ u32 impl, type, major, minor;
+
+ comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
+ if (!comp) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base)) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+ comp->base = base;
+
+ comp->cpu = -1;
+ for (int i = 0; ; i++) {
+ node = of_parse_phandle(dev->of_node, "cpus", i);
+ if (!node)
+ break;
+
+ ret = of_cpu_node_to_id(node);
+ of_node_put(node);
+ if (ret >= 0 && cpu_online(ret)) {
+ comp->cpu = ret;
+ break;
+ }
+ }
+
+ if (comp->cpu < 0) {
+ dev_err(dev, "No valid CPU found in 'cpus' property\n");
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ ret = rvtrace_component_reset(comp);
+ if (ret)
+ goto err_out;
+ comp->was_reset = true;
+
+ impl = readl_relaxed(comp->base + RVTRACE_COMPONENT_IMPL_OFFSET);
+ type = (impl >> RVTRACE_COMPONENT_IMPL_TYPE_SHIFT) &
+ RVTRACE_COMPONENT_IMPL_TYPE_MASK;
+ major = (impl >> RVTRACE_COMPONENT_IMPL_VERMAJOR_SHIFT) &
+ RVTRACE_COMPONENT_IMPL_VERMAJOR_MASK;
+ minor = (impl >> RVTRACE_COMPONENT_IMPL_VERMINOR_SHIFT) &
+ RVTRACE_COMPONENT_IMPL_VERMINOR_MASK;
+
+ comp->id.type = type;
+ comp->id.version = rvtrace_component_mkversion(major, minor);
+
+ return comp;
+
+err_out:
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(rvtrace_register_component);
diff --git a/include/linux/rvtrace.h b/include/linux/rvtrace.h
new file mode 100644
index 000000000000..e7028d82f8fd
--- /dev/null
+++ b/include/linux/rvtrace.h
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright(C) 2026 Spacemit Limited. All rights reserved.
+ */
+
+#ifndef __LINUX_RVTRACE_H__
+#define __LINUX_RVTRACE_H__
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/coresight.h>
+#include <linux/types.h>
+
+/* Control register common across all RISC-V trace components */
+#define RVTRACE_COMPONENT_CTRL_OFFSET 0x000
+#define RVTRACE_COMPONENT_CTRL_ACTIVE_MASK 0x1
+#define RVTRACE_COMPONENT_CTRL_ACTIVE_SHIFT 0
+#define RVTRACE_COMPONENT_CTRL_ENABLE_MASK 0x1
+#define RVTRACE_COMPONENT_CTRL_ENABLE_SHIFT 1
+#define RVTRACE_COMPONENT_CTRL_EMPTY_SHIFT 3
+
+/* Implementation register common across all RISC-V trace components */
+#define RVTRACE_COMPONENT_IMPL_OFFSET 0x004
+#define RVTRACE_COMPONENT_IMPL_VERMAJOR_MASK 0xf
+#define RVTRACE_COMPONENT_IMPL_VERMAJOR_SHIFT 0
+#define RVTRACE_COMPONENT_IMPL_VERMINOR_MASK 0xf
+#define RVTRACE_COMPONENT_IMPL_VERMINOR_SHIFT 4
+#define RVTRACE_COMPONENT_IMPL_TYPE_MASK 0xf
+#define RVTRACE_COMPONENT_IMPL_TYPE_SHIFT 8
+
+#define RVTRACE_TIMEOUT_US 100
+
+/* Possible component types defined by the RISC-V Trace Control Interface */
+enum rvtrace_component_type {
+ RVTRACE_COMPONENT_TYPE_RESV0,
+ RVTRACE_COMPONENT_TYPE_ENCODER, /* 0x1 */
+ RVTRACE_COMPONENT_TYPE_RESV2,
+ RVTRACE_COMPONENT_TYPE_RESV3,
+ RVTRACE_COMPONENT_TYPE_RESV4,
+ RVTRACE_COMPONENT_TYPE_RESV5,
+ RVTRACE_COMPONENT_TYPE_RESV6,
+ RVTRACE_COMPONENT_TYPE_RESV7,
+ RVTRACE_COMPONENT_TYPE_FUNNEL, /* 0x8 */
+ RVTRACE_COMPONENT_TYPE_RAMSINK, /* 0x9 */
+ RVTRACE_COMPONENT_TYPE_PIBSINK, /* 0xA */
+ RVTRACE_COMPONENT_TYPE_RESV11,
+ RVTRACE_COMPONENT_TYPE_RESV12,
+ RVTRACE_COMPONENT_TYPE_RESV13,
+ RVTRACE_COMPONENT_TYPE_ATBBRIDGE, /* 0xE */
+ RVTRACE_COMPONENT_TYPE_RESV15,
+ RVTRACE_COMPONENT_TYPE_MAX
+};
+
+/* Encoding/decoding macros for RISC-V trace component version */
+#define rvtrace_component_version_major(__version) \
+ (((__version) >> 16) & 0xffff)
+#define rvtrace_component_version_minor(__version) \
+ ((__version) & 0xffff)
+#define rvtrace_component_mkversion(__major, __minor) \
+ ((((__major) & 0xffff) << 16) | ((__minor) & 0xffff))
+
+/**
+ * struct rvtrace_component_id - Details to identify or match a RISC-V trace component
+ * @type: Type of the component
+ * @version: Version of the component
+ * @data: Data pointer for driver use
+ */
+struct rvtrace_component_id {
+ enum rvtrace_component_type type;
+ u32 version;
+ void *data;
+};
+
+/**
+ * struct rvtrace_component - Representation of a RISC-V trace component
+ * base: Memory mapped base address for the component
+ * id: Details to match the component
+ * dev: Device instance
+ * cpu: The cpu this component is affined to
+ * was_reset: Flag showing whether RISC-V trace driver was reset successfully
+ */
+struct rvtrace_component {
+ void __iomem *base;
+ struct rvtrace_component_id id;
+ struct device *dev;
+ int cpu;
+ bool was_reset;
+};
+
+struct component_enable_arg {
+ struct rvtrace_component *comp;
+ int rc;
+};
+
+struct rvtrace_component *rvtrace_register_component(struct platform_device *pdev);
+
+int rvtrace_poll_bit(struct rvtrace_component *comp, int offset,
+ int bit, int bitval);
+
+int rvtrace_enable_component(struct rvtrace_component *comp);
+int rvtrace_disable_component(struct rvtrace_component *comp);
+int rvtrace_component_reset(struct rvtrace_component *comp);
+
+static inline void *rvtrace_component_data(struct rvtrace_component *comp)
+{
+ return comp->id.data;
+}
+
+static inline int rvtrace_comp_is_empty(struct rvtrace_component *comp)
+{
+ return rvtrace_poll_bit(comp, RVTRACE_COMPONENT_CTRL_OFFSET,
+ RVTRACE_COMPONENT_CTRL_EMPTY_SHIFT, 1);
+}
+
+#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 ` Zane Leung [this message]
2026-04-14 3:41 ` [RFC PATCH 03/12] coresight: Add RISC-V Trace Encoder driver Zane Leung
2026-04-14 3:41 ` [RFC PATCH 04/12] coresight: Add RISC-V Trace Funnel driver Zane Leung
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-3-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