[PATCH RFC 02/12] rvtrace: Add pre-ratified implementation callback

From: Eric Lin

Date: Tue Jun 30 2026 - 05:52:13 EST


For pre-ratified trace hardware, the implementation register
bitfields differ from the ratified RISC-V trace specification,
and the component type is not defined in the hardware
implementation register.

To address this, add a get_impl() callback function in the
driver data to translate the pre-ratified trace hardware
implementation register information and encode it into the
standard RISC-V trace implementation register format.

Co-developed-by: Nick Hu <nick.hu@xxxxxxxxxx>
Signed-off-by: Nick Hu <nick.hu@xxxxxxxxxx>
Co-developed-by: Vincent Chen <vincent.chen@xxxxxxxxxx>
Signed-off-by: Vincent Chen <vincent.chen@xxxxxxxxxx>
Signed-off-by: Eric Lin <eric.lin@xxxxxxxxxx>
---
drivers/hwtracing/rvtrace/Kconfig | 9 ++++++++
drivers/hwtracing/rvtrace/Makefile | 1 +
drivers/hwtracing/rvtrace/rvtrace-platform.c | 21 +++++++++++++++++-
drivers/hwtracing/rvtrace/rvtrace-v0.c | 32 ++++++++++++++++++++++++++++
drivers/hwtracing/rvtrace/rvtrace-v0.h | 16 ++++++++++++++
include/linux/rvtrace.h | 8 +++++++
6 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/drivers/hwtracing/rvtrace/Kconfig b/drivers/hwtracing/rvtrace/Kconfig
index ba11acf1117d..5e84a3d0b633 100644
--- a/drivers/hwtracing/rvtrace/Kconfig
+++ b/drivers/hwtracing/rvtrace/Kconfig
@@ -31,3 +31,12 @@ config RVTRACE_RAMSINK
help
This driver provides support for Risc-V E-Trace Ramsink
component.
+
+config RVTRACE_V0
+ tristate "RISC-V Trace Pre-ratified driver"
+ depends on RVTRACE
+ select RVTRACE_ENCODER
+ select RVTRACE_RAMSINK
+ default y
+ help
+ This provides the RISC-V pre-ratified version trace hardware support.
diff --git a/drivers/hwtracing/rvtrace/Makefile b/drivers/hwtracing/rvtrace/Makefile
index 07403f4d94e3..51b292b1b4c4 100644
--- a/drivers/hwtracing/rvtrace/Makefile
+++ b/drivers/hwtracing/rvtrace/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0

+obj-$(CONFIG_RVTRACE_V0) += rvtrace-v0.o
obj-$(CONFIG_RVTRACE) += rvtrace.o
rvtrace-y := rvtrace-core.o rvtrace-platform.o rvtrace-perf.o
obj-$(CONFIG_RVTRACE_ENCODER) += rvtrace-encoder.o
diff --git a/drivers/hwtracing/rvtrace/rvtrace-platform.c b/drivers/hwtracing/rvtrace/rvtrace-platform.c
index 83e5a577bc52..6cf8e7dae2ad 100644
--- a/drivers/hwtracing/rvtrace/rvtrace-platform.c
+++ b/drivers/hwtracing/rvtrace/rvtrace-platform.c
@@ -11,6 +11,7 @@
#include <linux/property.h>
#include <linux/rvtrace.h>
#include <linux/types.h>
+#include "rvtrace-v0.h"

static int rvtrace_of_parse_outconns(struct rvtrace_platform_data *pdata)
{
@@ -114,6 +115,7 @@ static int rvtrace_of_parse_inconns(struct rvtrace_platform_data *pdata)

static int rvtrace_platform_probe(struct platform_device *pdev)
{
+ const struct rvtrace_driver_data *driver_data;
struct rvtrace_platform_data *pdata;
struct device *dev = &pdev->dev;
struct rvtrace_component *comp;
@@ -162,7 +164,14 @@ static int rvtrace_platform_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "failed to reset component\n");

- impl = rvtrace_read32(pdata, RVTRACE_COMPONENT_IMPL_OFFSET);
+ driver_data = device_get_match_data(pdata->dev);
+ if (driver_data) {
+ if (driver_data->get_impl)
+ impl = driver_data->get_impl(pdata);
+ } else {
+ impl = rvtrace_read32(pdata, RVTRACE_COMPONENT_IMPL_OFFSET);
+ }
+
type = (impl >> RVTRACE_COMPONENT_IMPL_TYPE_SHIFT) &
RVTRACE_COMPONENT_IMPL_TYPE_MASK;
major = (impl >> RVTRACE_COMPONENT_IMPL_VERMAJOR_SHIFT) &
@@ -194,8 +203,18 @@ static void rvtrace_platform_remove(struct platform_device *pdev)
rvtrace_unregister_component(comp);
}

+static const struct rvtrace_driver_data rvtrace_v0_encoder_data = {
+ .get_impl = rvtrace_v0_get_encoder_impl,
+};
+
+static const struct rvtrace_driver_data rvtrace_v0_funnel_data = {
+ .get_impl = rvtrace_v0_get_funnel_impl,
+};
+
static const struct of_device_id rvtrace_platform_match[] = {
{ .compatible = "riscv,trace-component" },
+ { .compatible = "sifive,trace-encoder0", .data = &rvtrace_v0_encoder_data},
+ { .compatible = "sifive,trace-funnel0", .data = &rvtrace_v0_funnel_data},
{}
};

diff --git a/drivers/hwtracing/rvtrace/rvtrace-v0.c b/drivers/hwtracing/rvtrace/rvtrace-v0.c
new file mode 100644
index 000000000000..825de1120c8d
--- /dev/null
+++ b/drivers/hwtracing/rvtrace/rvtrace-v0.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2026 SiFive Inc.
+ */
+
+#include <linux/rvtrace.h>
+#include "rvtrace-v0.h"
+
+static u32 rvtrace_v0_get_impl(struct rvtrace_platform_data *pdata, u32 type)
+{
+ u32 impl, major, minor;
+
+ impl = rvtrace_read32(pdata, RVTRACE_COMPONENT_IMPL_OFFSET);
+ major = 0;
+ minor = (impl >> RVTRACE_COMPONENT_IMPL_VERMAJOR_SHIFT) &
+ RVTRACE_COMPONENT_IMPL_VERMAJOR_MASK;
+
+ /* Encode to standard rvtrace impl format */
+ return (type << RVTRACE_COMPONENT_IMPL_TYPE_SHIFT) |
+ (minor << RVTRACE_COMPONENT_IMPL_VERMINOR_SHIFT) |
+ (major << RVTRACE_COMPONENT_IMPL_VERMAJOR_SHIFT);
+}
+
+u32 rvtrace_v0_get_encoder_impl(struct rvtrace_platform_data *pdata)
+{
+ return rvtrace_v0_get_impl(pdata, RVTRACE_COMPONENT_TYPE_ENCODER);
+}
+
+u32 rvtrace_v0_get_funnel_impl(struct rvtrace_platform_data *pdata)
+{
+ return rvtrace_v0_get_impl(pdata, RVTRACE_COMPONENT_TYPE_FUNNEL);
+}
diff --git a/drivers/hwtracing/rvtrace/rvtrace-v0.h b/drivers/hwtracing/rvtrace/rvtrace-v0.h
new file mode 100644
index 000000000000..511aa6489caa
--- /dev/null
+++ b/drivers/hwtracing/rvtrace/rvtrace-v0.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2026 SiFive, Inc.
+ *
+ */
+
+#ifndef __RVTRACE_V0_H__
+#define __RVTRACE_V0_H__
+
+#include <linux/rvtrace.h>
+
+u32 rvtrace_v0_get_encoder_impl(struct rvtrace_platform_data *pdata);
+u32 rvtrace_v0_get_funnel_impl(struct rvtrace_platform_data *pdata);
+
+#endif /* __RVTRACE_V0_H__ */
+
diff --git a/include/linux/rvtrace.h b/include/linux/rvtrace.h
index 0cb3bd474c2b..fdf6115d7f06 100644
--- a/include/linux/rvtrace.h
+++ b/include/linux/rvtrace.h
@@ -154,6 +154,14 @@ struct rvtrace_platform_data {
struct rvtrace_connection **outconns;
};

+/**
+ * struct rvtrace_driver_data - Driver-specific data for RISC-V trace components
+ * @get_impl: Optional callback to retrieve pre-ratified implementation register information.
+ */
+struct rvtrace_driver_data {
+ u32 (*get_impl)(struct rvtrace_platform_data *pdata);
+};
+
static inline u32 rvtrace_read32(struct rvtrace_platform_data *pdata, u32 offset)
{
if (likely(pdata->io_mem))

--
2.34.1