[PATCH RFC 06/12] rvtrace: Add pre-ratified trace sink config

From: Eric Lin

Date: Tue Jun 30 2026 - 05:53:47 EST


To decide which sink to send trace data to, pre-ratified trace
hardware (eg., SiFive) sets a sink bitfield directly within the
current component's control MMIO register.

Introduce rvtrace_v0_sink_config() for pre-ratified trace hardware
to correctly configure the destination sink based on the hardware
capabilities and the current trace path before starting the trace.

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/rvtrace-encoder.c | 27 +++++++++++-----------
drivers/hwtracing/rvtrace/rvtrace-v0.c | 35 +++++++++++++++++++++++++++++
drivers/hwtracing/rvtrace/rvtrace-v0.h | 15 +++++++++++++
3 files changed, 64 insertions(+), 13 deletions(-)

diff --git a/drivers/hwtracing/rvtrace/rvtrace-encoder.c b/drivers/hwtracing/rvtrace/rvtrace-encoder.c
index f3be47e448cf..47740bbdc206 100644
--- a/drivers/hwtracing/rvtrace/rvtrace-encoder.c
+++ b/drivers/hwtracing/rvtrace/rvtrace-encoder.c
@@ -6,6 +6,7 @@
#include <linux/device.h>
#include <linux/rvtrace.h>
#include <linux/types.h>
+#include "rvtrace-v0.h"

#define RVTRACE_COMPONENT_CTRL_ITRACE_SHIFT 2
#define RVTRACE_COMPONENT_CTRL_INSTMODE_SHIFT 4
@@ -15,14 +16,19 @@ static int rvtrace_encoder_start(struct rvtrace_path_node *node)
{
struct rvtrace_component *comp = node->comp;
int ret;
- u32 val;
+ u32 val, comp_maj;
+
+ /* Set pre-ratified comp's next sink */
+ comp_maj = rvtrace_component_version_major(comp->id.version);
+ if (comp_maj == 0) {
+ ret = rvtrace_v0_sink_config(node);
+ if (ret) {
+ dev_err(&comp->dev, "failed to set next sink.\n");
+ return ret;
+ }
+ }

- val = rvtrace_read32(comp->pdata, RVTRACE_COMPONENT_CTRL_OFFSET);
- val |= BIT(RVTRACE_COMPONENT_CTRL_ENABLE_SHIFT);
- rvtrace_write32(comp->pdata, val, RVTRACE_COMPONENT_CTRL_OFFSET);
- ret = rvtrace_poll_bit(comp->pdata, RVTRACE_COMPONENT_CTRL_OFFSET,
- RVTRACE_COMPONENT_CTRL_ENABLE_SHIFT, 1,
- comp->pdata->control_poll_timeout_usecs);
+ ret = rvtrace_enable_component(comp->pdata);
if (ret) {
dev_err(&comp->dev, "failed to enable encoder.\n");
return ret;
@@ -61,12 +67,7 @@ static int rvtrace_encoder_stop(struct rvtrace_component *comp)
return ret;
}

- val = rvtrace_read32(comp->pdata, RVTRACE_COMPONENT_CTRL_OFFSET);
- val &= ~BIT(RVTRACE_COMPONENT_CTRL_ENABLE_SHIFT);
- rvtrace_write32(comp->pdata, val, RVTRACE_COMPONENT_CTRL_OFFSET);
- ret = rvtrace_poll_bit(comp->pdata, RVTRACE_COMPONENT_CTRL_OFFSET,
- RVTRACE_COMPONENT_CTRL_ENABLE_SHIFT, 0,
- comp->pdata->control_poll_timeout_usecs);
+ ret = rvtrace_disable_component(comp->pdata);
if (ret) {
dev_err(&comp->dev, "failed to disable encoder.\n");
return ret;
diff --git a/drivers/hwtracing/rvtrace/rvtrace-v0.c b/drivers/hwtracing/rvtrace/rvtrace-v0.c
index bed35f631390..ba87e1f7a839 100644
--- a/drivers/hwtracing/rvtrace/rvtrace-v0.c
+++ b/drivers/hwtracing/rvtrace/rvtrace-v0.c
@@ -6,6 +6,41 @@
#include <linux/rvtrace.h>
#include "rvtrace-v0.h"

+int rvtrace_v0_sink_config(struct rvtrace_path_node *node)
+{
+ struct rvtrace_component *comp = node->comp;
+ struct rvtrace_path_node *next_node = NULL;
+ struct rvtrace_v0_comp_features *data = NULL;
+ u32 val;
+
+ data = (struct rvtrace_v0_comp_features *)comp->id.data;
+ if (!data)
+ return -EINVAL;
+
+ val = rvtrace_read32(comp->pdata, RVTRACE_COMPONENT_CTRL_OFFSET);
+ val &= ~RVTRACE_V0_CTRL_SINK_MASK;
+
+ /* last node in list */
+ if (!node->conn) {
+ if (data->has_sba_sink) {
+ val |= TE_SINK_SBA << RVTRACE_V0_CTRL_SINK_SHIFT;
+ } else {
+ dev_warn(&comp->dev,
+ "Component is last node but doesn't support SBA sink\n");
+ }
+ } else {
+ next_node = list_next_entry(node, head);
+ if (next_node && next_node->comp->id.type == RVTRACE_COMPONENT_TYPE_FUNNEL &&
+ data->has_funnel_sink) {
+ val |= TE_SINK_FUNNEL << RVTRACE_V0_CTRL_SINK_SHIFT;
+ }
+ }
+
+ rvtrace_write32(comp->pdata, val, RVTRACE_COMPONENT_CTRL_OFFSET);
+
+ return 0;
+}
+
void *rvtrace_v0_get_comp_data(struct rvtrace_platform_data *pdata)
{
struct rvtrace_v0_comp_features *data;
diff --git a/drivers/hwtracing/rvtrace/rvtrace-v0.h b/drivers/hwtracing/rvtrace/rvtrace-v0.h
index 562d3a77c513..48728fef24c0 100644
--- a/drivers/hwtracing/rvtrace/rvtrace-v0.h
+++ b/drivers/hwtracing/rvtrace/rvtrace-v0.h
@@ -9,6 +9,9 @@

#include <linux/rvtrace.h>

+#define RVTRACE_V0_CTRL_SINK_SHIFT 28
+#define RVTRACE_V0_CTRL_SINK_MASK GENMASK(31, RVTRACE_V0_CTRL_SINK_SHIFT)
+
#define RVTRACE_V0_IMPL_HAS_SRAM_SINK_BIT 4
#define RVTRACE_V0_IMPL_HAS_ATB_SINK_BIT 5
#define RVTRACE_V0_IMPL_HAS_PIB_SINK_BIT 6
@@ -21,6 +24,15 @@
#define RVTRACE_V0_IMPL_HAS_SBA_SINK_MASK BIT(RVTRACE_V0_IMPL_HAS_SBA_SINK_BIT)
#define RVTRACE_V0_IMPL_HAS_FUNNEL_SINK_MASK BIT(RVTRACE_V0_IMPL_HAS_FUNNEL_SINK_BIT)

+enum rvtrace_v0_sink {
+ TE_SINK_DEFAULT = 0,
+ TE_SINK_SRAM = 4,
+ TE_SINK_ATB = 5,
+ TE_SINK_PIB = 6,
+ TE_SINK_SBA = 7,
+ TE_SINK_FUNNEL = 8,
+};
+
struct rvtrace_v0_comp_features {
bool has_sram_sink;
bool has_atb_sink;
@@ -33,5 +45,8 @@ u32 rvtrace_v0_get_encoder_impl(struct rvtrace_platform_data *pdata);
u32 rvtrace_v0_get_funnel_impl(struct rvtrace_platform_data *pdata);
void *rvtrace_v0_get_comp_data(struct rvtrace_platform_data *pdata);

+int rvtrace_v0_sink_config(struct rvtrace_path_node *node);
+int rvtrace_v0_ramsink_setup(struct rvtrace_component *comp);
+
#endif /* __RVTRACE_V0_H__ */


--
2.34.1