Thread (13 messages) 13 messages, 1 author, 4d ago
COOLING4d

[PATCH RFC 08/12] rvtrace: Introduce struct rvtrace_ramsink_regs to abstract register offsets

From: Eric Lin <hidden>
Date: 2026-06-30 09:47:26
Also in: linux-riscv, lkml
Subsystem: hardware tracing facilities, the rest · Maintainers: Alexander Shishkin, Linus Torvalds

The pre-ratified trace ramsink implementation uses different register
offsets compared to the ratified RISC-V trace specification. To allow
the pre-ratified trace ramsink to leverage the rvtrace_ramsink_setup()
function, introduce 'struct rvtrace_ramsink_regs'. This abstracts the
register map, enabling both pre-ratified and ratified trace hardware
to provide their own register layouts.

Co-developed-by: Nick Hu <redacted>
Signed-off-by: Nick Hu <redacted>
Co-developed-by: Vincent Chen <redacted>
Signed-off-by: Vincent Chen <redacted>
Signed-off-by: Eric Lin <redacted>
---
 drivers/hwtracing/rvtrace/rvtrace-ramsink.c | 97 ++++++++++++++++++++++-------
 1 file changed, 76 insertions(+), 21 deletions(-)
diff --git a/drivers/hwtracing/rvtrace/rvtrace-ramsink.c b/drivers/hwtracing/rvtrace/rvtrace-ramsink.c
index 7aa525ac0f75..e569e875568b 100644
--- a/drivers/hwtracing/rvtrace/rvtrace-ramsink.c
+++ b/drivers/hwtracing/rvtrace/rvtrace-ramsink.c
@@ -26,6 +26,39 @@ enum rvtrace_ramsink_mode {
 	MODE_SMEM
 };
 
+/**
+ * struct rvtrace_ramsink_regs - Register offsets for RAM sink implementations
+ * @start_low:   Offset of the start address low register
+ * @start_high:  Offset of the start address high register
+ * @limit_low:   Offset of the limit address low register
+ * @limit_high:  Offset of the limit address high register
+ * @wp_low:      Offset of the write pointer low register
+ * @wp_high:     Offset of the write pointer high register
+ *
+ * Different RAM sink implementations may have different register layouts.
+ * This structure allows the common code to work with any layout.
+ */
+struct rvtrace_ramsink_regs {
+	u32 start_low;
+	u32 start_high;
+	u32 limit_low;
+	u32 limit_high;
+	u32 wp_low;
+	u32 wp_high;
+};
+
+/**
+ * struct rvtrace_ramsink_priv - Private data for RAM sink implementations
+ * @size:         Size of the allocated DMA buffer
+ * @va:           Virtual address of the DMA buffer
+ * @start:        DMA start address
+ * @end:          DMA end address
+ * @mode:         Ramsink mode (e.g., SRAM vs SMEM)
+ * @stop_on_wrap: Whether to stop tracing when buffer wraps
+ * @mem_acc_width: Memory access width in bytes
+ * @regs:         Pointer to register offset definitions
+ * @prev_wp:      Previous write pointer position (for incremental copies)
+ */
 struct rvtrace_ramsink_priv {
 	size_t size;
 	void *va;
@@ -34,15 +67,32 @@ struct rvtrace_ramsink_priv {
 	enum rvtrace_ramsink_mode mode;
 	bool stop_on_wrap;
 	int mem_acc_width;
+	const struct rvtrace_ramsink_regs *regs;
 	u64 prev_wp;
 };
 
+/**
+ * struct trace_buf - Trace buffer descriptor for copy operations
+ * @base: Base address of the buffer
+ * @cur:  Current position in the buffer
+ * @len:  Length of the buffer
+ */
 struct trace_buf {
 	void *base;
 	size_t cur;
 	size_t len;
 };
 
+/* Register offsets for the standard RISC-V trace ramsink */
+static const struct rvtrace_ramsink_regs rvtrace_std_ramsink_regs = {
+	.start_low    = RVTRACE_RAMSINK_STARTLOW_OFF,
+	.start_high   = RVTRACE_RAMSINK_STARTHIGH_OFF,
+	.limit_low    = RVTRACE_RAMSINK_LIMITLOW_OFF,
+	.limit_high   = RVTRACE_RAMSINK_LIMITHIGH_OFF,
+	.wp_low       = RVTRACE_RAMSINK_WPLOW_OFF,
+	.wp_high      = RVTRACE_RAMSINK_WPHIGH_OFF,
+};
+
 static int rvtrace_ramsink_start(struct rvtrace_path_node *node)
 {
 	struct rvtrace_component *comp = node->comp;
@@ -117,6 +167,7 @@ static size_t rvtrace_ramsink_copyto_auxbuf(struct rvtrace_component *comp,
 					    struct rvtrace_perf_auxbuf *buf)
 {
 	struct rvtrace_ramsink_priv *priv = dev_get_drvdata(&comp->dev);
+	const struct rvtrace_ramsink_regs *regs = priv->regs;
 	struct trace_buf src, dst;
 	u32 wp_low, wp_high;
 	size_t bytes = 0;
@@ -128,16 +179,17 @@ static size_t rvtrace_ramsink_copyto_auxbuf(struct rvtrace_component *comp,
 	dst.cur = buf->pos;
 	src.base = priv->va;
 	src.len = priv->size;
-	wp_low = rvtrace_read32(comp->pdata, RVTRACE_RAMSINK_WPLOW_OFF);
-	wp_high = rvtrace_read32(comp->pdata, RVTRACE_RAMSINK_WPHIGH_OFF);
-	wp = (u64)(wp_high) << 32 | wp_low;
+
+	wp_low = rvtrace_read32(comp->pdata, regs->wp_low);
+	wp_high = rvtrace_read32(comp->pdata, regs->wp_high);
+	wp = (u64)wp_high << 32 | wp_low;
 	wrap = wp & RVTRACE_RAMSINK_WPLOW_WRAP;
 	wp &= ~RVTRACE_RAMSINK_WPLOW_WRAP;
 	if (wrap) {
 		rvtrace_write32(comp->pdata, lower_32_bits(priv->start),
-				RVTRACE_RAMSINK_WPLOW_OFF);
+				regs->wp_low);
 		rvtrace_write32(comp->pdata, upper_32_bits(priv->start),
-				RVTRACE_RAMSINK_WPHIGH_OFF);
+				regs->wp_high);
 		src.cur = wp - priv->start;
 		priv->prev_wp = priv->start;
 		/*
@@ -160,22 +212,23 @@ static size_t rvtrace_ramsink_copyto_auxbuf(struct rvtrace_component *comp,
 static int rvtrace_ramsink_setup_buf(struct rvtrace_component *comp,
 				     struct rvtrace_ramsink_priv *priv)
 {
+	const struct rvtrace_ramsink_regs *regs = priv->regs;
 	struct device *pdev = comp->pdata->dev;
 	u64 start_min, limit_max, end;
 	u32 low, high;
 	int ret;
 
 	/* Probe min and max values for start and limit registers */
-	rvtrace_write32(comp->pdata, 0, RVTRACE_RAMSINK_STARTLOW_OFF);
-	rvtrace_write32(comp->pdata, 0, RVTRACE_RAMSINK_STARTHIGH_OFF);
-	low = rvtrace_read32(comp->pdata, RVTRACE_RAMSINK_STARTLOW_OFF);
-	high = rvtrace_read32(comp->pdata, RVTRACE_RAMSINK_STARTHIGH_OFF);
+	rvtrace_write32(comp->pdata, 0, regs->start_low);
+	rvtrace_write32(comp->pdata, 0, regs->start_high);
+	low = rvtrace_read32(comp->pdata, regs->start_low);
+	high = rvtrace_read32(comp->pdata, regs->start_high);
 	start_min = (u64)(high) << 32 | low;
 
-	rvtrace_write32(comp->pdata, 0xffffffff, RVTRACE_RAMSINK_LIMITLOW_OFF);
-	rvtrace_write32(comp->pdata, 0xffffffff, RVTRACE_RAMSINK_LIMITHIGH_OFF);
-	low = rvtrace_read32(comp->pdata, RVTRACE_RAMSINK_LIMITLOW_OFF);
-	high = rvtrace_read32(comp->pdata, RVTRACE_RAMSINK_LIMITHIGH_OFF);
+	rvtrace_write32(comp->pdata, 0xffffffff, regs->limit_low);
+	rvtrace_write32(comp->pdata, 0xffffffff, regs->limit_high);
+	low = rvtrace_read32(comp->pdata, regs->limit_low);
+	high = rvtrace_read32(comp->pdata, regs->limit_high);
 	limit_max = (u64)(high) << 32 | low;
 
 	/* Set DMA mask based on the maximum allowed limit address */
@@ -203,10 +256,10 @@ static int rvtrace_ramsink_setup_buf(struct rvtrace_component *comp,
 		priv->start = start_min;
 	}
 
-	rvtrace_write32(comp->pdata, lower_32_bits(priv->start), RVTRACE_RAMSINK_STARTLOW_OFF);
-	rvtrace_write32(comp->pdata, upper_32_bits(priv->start), RVTRACE_RAMSINK_STARTHIGH_OFF);
-	rvtrace_write32(comp->pdata, lower_32_bits(priv->start), RVTRACE_RAMSINK_WPLOW_OFF);
-	rvtrace_write32(comp->pdata, upper_32_bits(priv->start), RVTRACE_RAMSINK_WPHIGH_OFF);
+	rvtrace_write32(comp->pdata, lower_32_bits(priv->start), regs->start_low);
+	rvtrace_write32(comp->pdata, upper_32_bits(priv->start), regs->start_high);
+	rvtrace_write32(comp->pdata, lower_32_bits(priv->start), regs->wp_low);
+	rvtrace_write32(comp->pdata, upper_32_bits(priv->start), regs->wp_high);
 	/* Setup ram sink limit addresses */
 	if (priv->end > limit_max) {
 		dev_warn(&comp->dev, "Ramsink limit address updated from %pad to %pad\n",
@@ -217,10 +270,10 @@ static int rvtrace_ramsink_setup_buf(struct rvtrace_component *comp,
 
 	/* Limit address needs to be set to end - mem_access_width to avoid overflow */
 	end = priv->end - priv->mem_acc_width;
-	rvtrace_write32(comp->pdata, lower_32_bits(end), RVTRACE_RAMSINK_LIMITLOW_OFF);
-	rvtrace_write32(comp->pdata, upper_32_bits(end), RVTRACE_RAMSINK_LIMITHIGH_OFF);
-	low = rvtrace_read32(comp->pdata, RVTRACE_RAMSINK_LIMITLOW_OFF);
-	high = rvtrace_read32(comp->pdata, RVTRACE_RAMSINK_LIMITHIGH_OFF);
+	rvtrace_write32(comp->pdata, lower_32_bits(end), regs->limit_low);
+	rvtrace_write32(comp->pdata, upper_32_bits(end), regs->limit_high);
+	low = rvtrace_read32(comp->pdata, regs->limit_low);
+	high = rvtrace_read32(comp->pdata, regs->limit_high);
 	end = (u64)(high) << 32 | low;
 	if (end != (priv->end - 4)) {
 		dev_warn(&comp->dev, "Ramsink limit address updated from %pad to %pad\n",
@@ -252,6 +305,8 @@ static int rvtrace_ramsink_setup(struct rvtrace_component *comp)
 		break;
 	}
 
+	priv->regs = &rvtrace_std_ramsink_regs;
+
 	trram_ctrl = rvtrace_read32(comp->pdata, RVTRACE_COMPONENT_CTRL_OFFSET);
 	trram_ctrl |= priv->mode << RVTRACE_RAMSINK_CTRL_MODE_SHIFT;
 	rvtrace_write32(comp->pdata, trram_ctrl, RVTRACE_COMPONENT_CTRL_OFFSET);
-- 
2.34.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help