All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] renesas: vsp1: debugfs facility
@ 2022-06-29 10:51 Kieran Bingham
  2022-06-29 10:51 ` [PATCH 1/7] debugfs: Extend debugfs regset to support register decoding Kieran Bingham
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Kieran Bingham @ 2022-06-29 10:51 UTC (permalink / raw)
  To: linux-renesas-soc, linux-media, Eugeniu Rosca
  Cc: Laurent Pinchart, Kieran Bingham

As discussed during the thread on [0] here are my out of tree debug
patches.

These are only really for reference not expected for merge, and I'm not
even sure it's worthy of an RFC tag. That said, if there are parts here
that should perhaps be extracted for integration let me know and I'll
split things out if relevant.

The register extraction and decode is probably something that could be
handled in userspace now anyway with something like Tomi's rwmem debug
tool [1]. I've used that for other devices, but not used it on vsp1 yet.


[0] https://lore.kernel.org/linux-media/20220629090912.GA27332@lxhi-065/T/#t
[1] https://github.com/tomba/rwmem



Kieran Bingham (7):
  debugfs: Extend debugfs regset to support register decoding
  v4l: vsp1: Provide WPF underflow error detection and reporting
  v4l: vsp1: Add debugfs system v1.8
  v4l: vsp1: Add CLK_CTRL and MRESET register definitions
  v4l: vsp1: Add safety mechanism registers
  v4l: vsp1: Provide video node debugfs entries
  v4l: vsp1: debugfs: Add DLM directory

 drivers/media/platform/renesas/vsp1/Makefile  |   1 +
 drivers/media/platform/renesas/vsp1/vsp1.h    |   5 +
 .../platform/renesas/vsp1/vsp1_debugfs.c      | 563 ++++++++++++++++++
 .../platform/renesas/vsp1/vsp1_debugfs.h      |  57 ++
 drivers/media/platform/renesas/vsp1/vsp1_dl.c | 107 ++++
 .../media/platform/renesas/vsp1/vsp1_drv.c    |  13 +-
 .../media/platform/renesas/vsp1/vsp1_regs.h   |  36 ++
 .../media/platform/renesas/vsp1/vsp1_video.c  |  14 +-
 .../media/platform/renesas/vsp1/vsp1_video.h  |   9 +
 .../media/platform/renesas/vsp1/vsp1_wpf.c    |   2 +-
 fs/debugfs/file.c                             |  11 +-
 include/linux/debugfs.h                       |   1 +
 12 files changed, 814 insertions(+), 5 deletions(-)
 create mode 100644 drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
 create mode 100644 drivers/media/platform/renesas/vsp1/vsp1_debugfs.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/7] debugfs: Extend debugfs regset to support register decoding
  2022-06-29 10:51 [PATCH 0/7] renesas: vsp1: debugfs facility Kieran Bingham
@ 2022-06-29 10:51 ` Kieran Bingham
  2022-06-29 10:51 ` [PATCH 2/7] v4l: vsp1: Provide WPF underflow error detection and reporting Kieran Bingham
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kieran Bingham @ 2022-06-29 10:51 UTC (permalink / raw)
  To: linux-renesas-soc, linux-media, Eugeniu Rosca
  Cc: Laurent Pinchart, Kieran Bingham

Allow regsets to provide a function to present decoded information on
register usage. This allows a static function to be passed the value
read from the register and present the information in a human readable
form.

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

---
This is purely RFC / Personal debug use only.

- I'm not currently recommending/suggesting/asking for this change to
  the core debugfs infrastructure.

- I have not put effort into design, or thought about how this should be
  done, this is just something I use locally as a quick hack.

- I would likely use https://github.com/tomba/rwmem if I were to tackle
  this again now.

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
---
 fs/debugfs/file.c       | 11 +++++++++--
 include/linux/debugfs.h |  1 +
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 950c63fa4d0b..b777d558ea0c 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -1111,10 +1111,17 @@ void debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs,
 	int i;
 
 	for (i = 0; i < nregs; i++, regs++) {
+		u32 value = readl(base + regs->offset);
 		if (prefix)
 			seq_printf(s, "%s", prefix);
-		seq_printf(s, "%s = 0x%08x\n", regs->name,
-			   readl(base + regs->offset));
+
+		seq_printf(s, "%s = 0x%08x", regs->name, value);
+
+		if (regs->decode_reg)
+			regs->decode_reg(s, value);
+
+		seq_puts(s, "\n");
+
 		if (seq_has_overflowed(s))
 			break;
 	}
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index c869f1e73d75..70dc487c03ed 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -29,6 +29,7 @@ struct debugfs_blob_wrapper {
 struct debugfs_reg32 {
 	char *name;
 	unsigned long offset;
+	void (*decode_reg)(struct seq_file *s, u32 value);
 };
 
 struct debugfs_regset32 {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/7] v4l: vsp1: Provide WPF underflow error detection and reporting
  2022-06-29 10:51 [PATCH 0/7] renesas: vsp1: debugfs facility Kieran Bingham
  2022-06-29 10:51 ` [PATCH 1/7] debugfs: Extend debugfs regset to support register decoding Kieran Bingham
@ 2022-06-29 10:51 ` Kieran Bingham
  2022-06-29 10:51 ` [PATCH 3/7] v4l: vsp1: Add debugfs system v1.8 Kieran Bingham
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kieran Bingham @ 2022-06-29 10:51 UTC (permalink / raw)
  To: linux-renesas-soc, linux-media, Eugeniu Rosca
  Cc: Laurent Pinchart, Kieran Bingham

In erroneous conditions, the WPF can assert an underrun interrupt. This
usually represents a mis-configured pipeline, or bus priority issue. It
is likely that in the event of this interrupt being asserted the
hardware is no longer operational. A device error message at the least
is useful in this scenario

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
---
 drivers/media/platform/renesas/vsp1/vsp1_drv.c  | 8 +++++++-
 drivers/media/platform/renesas/vsp1/vsp1_regs.h | 2 ++
 drivers/media/platform/renesas/vsp1/vsp1_wpf.c  | 2 +-
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/renesas/vsp1/vsp1_drv.c b/drivers/media/platform/renesas/vsp1/vsp1_drv.c
index 1f73c48eb738..392aced46758 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_drv.c
@@ -44,7 +44,8 @@
 
 static irqreturn_t vsp1_irq_handler(int irq, void *data)
 {
-	u32 mask = VI6_WPF_IRQ_STA_DFE | VI6_WPF_IRQ_STA_FRE;
+	u32 mask = VI6_WPF_IRQ_STA_UND | VI6_WPF_IRQ_STA_DFE |
+		   VI6_WPF_IRQ_STA_FRE;
 	struct vsp1_device *vsp1 = data;
 	irqreturn_t ret = IRQ_NONE;
 	unsigned int i;
@@ -63,6 +64,11 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
 			vsp1_pipeline_frame_end(wpf->entity.pipe);
 			ret = IRQ_HANDLED;
 		}
+
+		if (status & VI6_WPF_IRQ_STA_UND) {
+			dev_err(vsp1->dev, "WPF[%d] Underflow error\n", i);
+			ret = IRQ_HANDLED;
+		}
 	}
 
 	return ret;
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_regs.h b/drivers/media/platform/renesas/vsp1/vsp1_regs.h
index fae7286eb01e..632c43bb4cbd 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/renesas/vsp1/vsp1_regs.h
@@ -32,10 +32,12 @@
 #define VI6_STATUS_SYS_ACT(n)		BIT((n) + 8)
 
 #define VI6_WPF_IRQ_ENB(n)		(0x0048 + (n) * 12)
+#define VI6_WPF_IRQ_ENB_UNDE		BIT(16)
 #define VI6_WPF_IRQ_ENB_DFEE		BIT(1)
 #define VI6_WPF_IRQ_ENB_FREE		BIT(0)
 
 #define VI6_WPF_IRQ_STA(n)		(0x004c + (n) * 12)
+#define VI6_WPF_IRQ_STA_UND		BIT(16)
 #define VI6_WPF_IRQ_STA_DFE		BIT(1)
 #define VI6_WPF_IRQ_STA_FRE		BIT(0)
 
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_wpf.c b/drivers/media/platform/renesas/vsp1/vsp1_wpf.c
index 94e91d7bb56c..28f01f98fd6b 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_wpf.c
@@ -342,7 +342,7 @@ static void wpf_configure_stream(struct vsp1_entity *entity,
 	/* Enable interrupts. */
 	vsp1_dl_body_write(dlb, VI6_WPF_IRQ_STA(index), 0);
 	vsp1_dl_body_write(dlb, VI6_WPF_IRQ_ENB(index),
-			   VI6_WPF_IRQ_ENB_DFEE);
+			   VI6_WPF_IRQ_ENB_DFEE | VI6_WPF_IRQ_ENB_UNDE);
 
 	/*
 	 * Configure writeback for display pipelines (the wpf writeback flag is
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/7] v4l: vsp1: Add debugfs system v1.8
  2022-06-29 10:51 [PATCH 0/7] renesas: vsp1: debugfs facility Kieran Bingham
  2022-06-29 10:51 ` [PATCH 1/7] debugfs: Extend debugfs regset to support register decoding Kieran Bingham
  2022-06-29 10:51 ` [PATCH 2/7] v4l: vsp1: Provide WPF underflow error detection and reporting Kieran Bingham
@ 2022-06-29 10:51 ` Kieran Bingham
  2022-06-29 10:51 ` [PATCH 4/7] v4l: vsp1: Add CLK_CTRL and MRESET register definitions Kieran Bingham
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kieran Bingham @ 2022-06-29 10:51 UTC (permalink / raw)
  To: linux-renesas-soc, linux-media, Eugeniu Rosca
  Cc: Laurent Pinchart, Kieran Bingham

Provide a directory under the debugfs filesystem where extra
information can be requested when debugging the hardware.

Status information for the WPF is presented under info.
Registers can be inspected in regs

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

Changelog:

v1.1
 - Fix the regs_local vsp1 pointer that is passed to get the device
   references

v1.2
 - Fix up the RPF extension so that it displays the RPF number on those
   specific regset entries

v1.3
- Fix regs_local buffer size (Currently consuming at least 6k)
- Add a 'reset wpf' hook
- Add in VI6_CMD register reads
- Add in MRESET and Dynamic clock control registers
- Provide decode for vi6_disp_irq_sta
- Remove LookUpTable registers as they are not available on all cells
- Provide IRQ Enable status as well as level status

v1.4
- Move debugfs init/clean to probe/remove
- use devname(dev) to create the VSP debugfs root dir
- Remove 'Hard PM lock' which kept VSP's permanantly clocked

V1.5:
 - Add 'pipe' reporting to start looking at other internals.
 - Also adds 'RPF' iterations to examine there
 - checkpatch.pl fixups (most of them at least)

v1.6:
 - Convert to seq_file usage (much nicer)
 - Temporarily drop HISTO registers until mainline catches up

1.7:
 - convert WPF IRQ STA/ENB decodes to seq_printf helpers
 - reformat the DISP helper spacing
 - convert to using decode_vi6_disp_irq_sta now it's relevant
 - Simplify DEBUGFS_RO_ATTR macro
 - Provide seq_file based vsp1_reg_decode()

1.8:
 - Rebase to 5.12
 - Remove registers not in mainline
 - Adapt to register updates which now take parameters
 - Make local functions static
 - Add Writeback mode decode
 - Fix newlines, don't repeat the register value

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
---
 drivers/media/platform/renesas/vsp1/Makefile  |   1 +
 drivers/media/platform/renesas/vsp1/vsp1.h    |   4 +
 .../platform/renesas/vsp1/vsp1_debugfs.c      | 508 ++++++++++++++++++
 .../platform/renesas/vsp1/vsp1_debugfs.h      |  49 ++
 .../media/platform/renesas/vsp1/vsp1_drv.c    |   5 +
 5 files changed, 567 insertions(+)
 create mode 100644 drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
 create mode 100644 drivers/media/platform/renesas/vsp1/vsp1_debugfs.h

diff --git a/drivers/media/platform/renesas/vsp1/Makefile b/drivers/media/platform/renesas/vsp1/Makefile
index 4bb4dcbef7b5..33c7250fd03b 100644
--- a/drivers/media/platform/renesas/vsp1/Makefile
+++ b/drivers/media/platform/renesas/vsp1/Makefile
@@ -6,5 +6,6 @@ vsp1-y					+= vsp1_clu.o vsp1_hsit.o vsp1_lut.o
 vsp1-y					+= vsp1_brx.o vsp1_sru.o vsp1_uds.o
 vsp1-y					+= vsp1_hgo.o vsp1_hgt.o vsp1_histo.o
 vsp1-y					+= vsp1_lif.o vsp1_uif.o
+vsp1-$(CONFIG_DEBUG_FS)			+= vsp1_debugfs.o
 
 obj-$(CONFIG_VIDEO_RENESAS_VSP1)	+= vsp1.o
diff --git a/drivers/media/platform/renesas/vsp1/vsp1.h b/drivers/media/platform/renesas/vsp1/vsp1.h
index 37cf33c7e6ca..1951d350b60a 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1.h
+++ b/drivers/media/platform/renesas/vsp1/vsp1.h
@@ -9,6 +9,7 @@
 #ifndef __VSP1_H__
 #define __VSP1_H__
 
+#include <linux/debugfs.h>
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
@@ -103,6 +104,9 @@ struct vsp1_device {
 	struct media_entity_operations media_ops;
 
 	struct vsp1_drm *drm;
+
+	struct debugfs_regset32 regset;
+	struct dentry *dbgroot;
 };
 
 int vsp1_device_get(struct vsp1_device *vsp1);
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
new file mode 100644
index 000000000000..4e361fd4c445
--- /dev/null
+++ b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
@@ -0,0 +1,508 @@
+/*
+ * vsp1_debugfs.c  --  R-Car VSP1 driver debug support
+ *
+ * Copyright (C) 2016 Renesas Electronics Corporation
+ *
+ * Contact: Kieran Bingham (kieran.bingham@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "vsp1.h"
+#include "vsp1_rwpf.h"
+#include "vsp1_pipe.h"
+
+#include "vsp1_debugfs.h"
+
+/* -----------------------------------------------------------------------------
+ * Data Tables
+ */
+
+/*
+ * Register maps can be generated with something similar to this expression:
+ *  cat vsp1_regs.h | \
+ *	grep -E "#define VI6_.*0[xX][0-9a-fA-F]{4}$" | \
+ *	sed -r 's/^#define (VI6\w*).*$/\tVSP1_DBFS_REG(\1),/'
+ */
+
+/* Do not use __stringify() here as that will expand the macros */
+#define VSP1_DBFS_REG(reg) { #reg, reg, NULL }
+#define VSP1_DBFS_REG_DECODE(reg, func)  { #reg, reg, func }
+
+static void decode_vi6_status(struct seq_file *s, u32 val)
+{
+	seq_printf(s, " WPF0 = %s : WPF1 = %s",
+		   val & VI6_STATUS_SYS_ACT(0) ? "active" : "inactive",
+		   val & VI6_STATUS_SYS_ACT(1) ? "active" : "inactive");
+}
+
+static void decode_vi6_disp_irq_sta(struct seq_file *s, u32 val)
+{
+	seq_printf(s, " %s%s%s%s%s%s%s",
+		   val & VI6_DISP_IRQ_STA_DST ? " DST" : "",
+		   val & VI6_DISP_IRQ_STA_MAE ? " MAE" : "",
+		   val & VI6_DISP_IRQ_STA_LNE(0) ? " LNE(0)" : "",
+		   val & VI6_DISP_IRQ_STA_LNE(1) ? " LNE(1)" : "",
+		   val & VI6_DISP_IRQ_STA_LNE(2) ? " LNE(2)" : "",
+		   val & VI6_DISP_IRQ_STA_LNE(3) ? " LNE(3)" : "",
+		   val & VI6_DISP_IRQ_STA_LNE(4) ? " LNE(4)" : "");
+}
+
+static void decode_vi6_wpf_enb(struct seq_file *s, u32 enable)
+{
+	seq_printf(s, " %s%s%s",
+		   enable & VI6_WPF_IRQ_ENB_UNDE ? " UND" : "",
+		   enable & VI6_WPF_IRQ_ENB_DFEE ? " DFE" : "",
+		   enable & VI6_WPF_IRQ_ENB_FREE ? " FRE" : "");
+}
+
+static void decode_vi6_wpf_sta(struct seq_file *s, u32 status)
+{
+	seq_printf(s, " %s%s%s",
+		   status & VI6_WPF_IRQ_STA_UND ? " UND" : "",
+		   status & VI6_WPF_IRQ_STA_DFE ? " DFE" : "",
+		   status & VI6_WPF_IRQ_STA_FRE ? " FRE" : "");
+}
+
+static void decode_vi6_wpf_wrbck_ctrl(struct seq_file *s, u32 reg)
+{
+	seq_printf(s, " %s",
+		   reg & VI6_WPF_WRBCK_CTRL_WBMD ? " WBMD" : "");
+}
+
+/* RPF is a special case that defines multiple sets of the same registers */
+#define VSP1_DBFS_RPF_REG(reg, idx) \
+	{ #reg "[" #idx "]", (reg + idx * VI6_RPF_OFFSET), NULL }
+
+#define VSP1_DBFS_RPF(index) \
+	\
+	VSP1_DBFS_RPF_REG(VI6_RPF_SRC_BSIZE, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_SRC_ESIZE, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_INFMT, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_DSWAP, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_LOC, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_ALPH_SEL, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_VRTCOL_SET, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_MSK_CTRL, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_MSK_SET0, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_MSK_SET1, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_CKEY_CTRL, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_CKEY_SET0, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_CKEY_SET1, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_SRCM_PSTRIDE, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_SRCM_ASTRIDE, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_SRCM_ADDR_Y, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_SRCM_ADDR_C0, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_SRCM_ADDR_C1, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_SRCM_ADDR_AI, index), \
+	VSP1_DBFS_RPF_REG(VI6_RPF_MULT_ALPHA, index)
+
+static const struct debugfs_reg32 vsp1_regset[] = {
+	VSP1_DBFS_REG(VI6_CMD(0)),
+	VSP1_DBFS_REG(VI6_CMD(1)),
+
+	VSP1_DBFS_REG(VI6_CLK_DCSWT),
+
+	VSP1_DBFS_REG(VI6_SRESET),
+
+	VSP1_DBFS_REG_DECODE(VI6_STATUS, decode_vi6_status),
+
+	VSP1_DBFS_REG_DECODE(VI6_WPF_IRQ_ENB(0), decode_vi6_wpf_enb),
+	VSP1_DBFS_REG_DECODE(VI6_WPF_IRQ_ENB(1), decode_vi6_wpf_enb),
+	VSP1_DBFS_REG_DECODE(VI6_WPF_IRQ_STA(0), decode_vi6_wpf_sta),
+	VSP1_DBFS_REG_DECODE(VI6_WPF_IRQ_STA(1), decode_vi6_wpf_sta),
+
+	VSP1_DBFS_REG(VI6_DISP_IRQ_ENB(0)),
+	VSP1_DBFS_REG(VI6_DISP_IRQ_ENB(1)),
+
+	VSP1_DBFS_REG_DECODE(VI6_DISP_IRQ_STA(0), decode_vi6_disp_irq_sta),
+	VSP1_DBFS_REG_DECODE(VI6_DISP_IRQ_STA(1), decode_vi6_disp_irq_sta),
+
+	VSP1_DBFS_REG(VI6_DL_CTRL),
+	VSP1_DBFS_REG(VI6_DL_SWAP),
+	VSP1_DBFS_REG(VI6_DL_EXT_CTRL(0)),
+	VSP1_DBFS_REG(VI6_DL_EXT_CTRL(1)),
+
+	VSP1_DBFS_REG(VI6_DL_BODY_SIZE),
+
+	VSP1_DBFS_RPF(0),
+	VSP1_DBFS_RPF(1),
+	VSP1_DBFS_RPF(2),
+	VSP1_DBFS_RPF(3),
+	VSP1_DBFS_RPF(4),
+
+	VSP1_DBFS_REG(VI6_WPF_SRCRPF),
+	VSP1_DBFS_REG(VI6_WPF_HSZCLIP),
+	VSP1_DBFS_REG(VI6_WPF_VSZCLIP),
+	VSP1_DBFS_REG(VI6_WPF_OUTFMT),
+	VSP1_DBFS_REG(VI6_WPF_DSWAP),
+	VSP1_DBFS_REG(VI6_WPF_RNDCTRL),
+	VSP1_DBFS_REG(VI6_WPF_ROT_CTRL),
+	VSP1_DBFS_REG(VI6_WPF_DSTM_STRIDE_Y),
+	VSP1_DBFS_REG(VI6_WPF_DSTM_STRIDE_C),
+	VSP1_DBFS_REG(VI6_WPF_DSTM_ADDR_Y),
+	VSP1_DBFS_REG(VI6_WPF_DSTM_ADDR_C0),
+	VSP1_DBFS_REG(VI6_WPF_DSTM_ADDR_C1),
+
+	VSP1_DBFS_REG_DECODE(VI6_WPF_WRBCK_CTRL(0), decode_vi6_wpf_wrbck_ctrl),
+
+	VSP1_DBFS_REG(VI6_DPR_RPF_ROUTE(0)),
+	VSP1_DBFS_REG(VI6_DPR_RPF_ROUTE(1)),
+	VSP1_DBFS_REG(VI6_DPR_RPF_ROUTE(2)),
+	VSP1_DBFS_REG(VI6_DPR_RPF_ROUTE(3)),
+	VSP1_DBFS_REG(VI6_DPR_RPF_ROUTE(4)),
+
+	VSP1_DBFS_REG(VI6_DPR_WPF_FPORCH(0)),
+	VSP1_DBFS_REG(VI6_DPR_WPF_FPORCH(1)),
+
+	VSP1_DBFS_REG(VI6_DPR_SRU_ROUTE),
+
+	VSP1_DBFS_REG(VI6_DPR_UDS_ROUTE(0)),
+
+	VSP1_DBFS_REG(VI6_DPR_LUT_ROUTE),
+	VSP1_DBFS_REG(VI6_DPR_CLU_ROUTE),
+	VSP1_DBFS_REG(VI6_DPR_HST_ROUTE),
+	VSP1_DBFS_REG(VI6_DPR_HSI_ROUTE),
+	VSP1_DBFS_REG(VI6_DPR_BRU_ROUTE),
+	VSP1_DBFS_REG(VI6_DPR_HGO_SMPPT),
+	VSP1_DBFS_REG(VI6_DPR_HGT_SMPPT),
+
+	VSP1_DBFS_REG(VI6_SRU_CTRL0),
+	VSP1_DBFS_REG(VI6_SRU_CTRL1),
+	VSP1_DBFS_REG(VI6_SRU_CTRL2),
+
+	VSP1_DBFS_REG(VI6_UDS_CTRL),
+	VSP1_DBFS_REG(VI6_UDS_SCALE),
+	VSP1_DBFS_REG(VI6_UDS_ALPTH),
+	VSP1_DBFS_REG(VI6_UDS_ALPVAL),
+	VSP1_DBFS_REG(VI6_UDS_PASS_BWIDTH),
+	VSP1_DBFS_REG(VI6_UDS_HPHASE),
+	VSP1_DBFS_REG(VI6_UDS_IPC),
+	VSP1_DBFS_REG(VI6_UDS_HSZCLIP),
+	VSP1_DBFS_REG(VI6_UDS_CLIP_SIZE),
+	VSP1_DBFS_REG(VI6_UDS_FILL_COLOR),
+
+	VSP1_DBFS_REG(VI6_LUT_CTRL),
+	VSP1_DBFS_REG(VI6_CLU_CTRL),
+	VSP1_DBFS_REG(VI6_HST_CTRL),
+	VSP1_DBFS_REG(VI6_HSI_CTRL),
+
+	VSP1_DBFS_REG(VI6_BRU_INCTRL),
+	VSP1_DBFS_REG(VI6_BRU_VIRRPF_SIZE),
+	VSP1_DBFS_REG(VI6_BRU_VIRRPF_LOC),
+	VSP1_DBFS_REG(VI6_BRU_VIRRPF_COL),
+
+	VSP1_DBFS_REG(VI6_BRU_CTRL(0)),
+	VSP1_DBFS_REG(VI6_BRU_CTRL(1)),
+	VSP1_DBFS_REG(VI6_BRU_CTRL(2)),
+	VSP1_DBFS_REG(VI6_BRU_CTRL(3)),
+	VSP1_DBFS_REG(VI6_BRU_CTRL(4)),
+
+	VSP1_DBFS_REG(VI6_BRU_BLD(0)),
+	VSP1_DBFS_REG(VI6_BRU_BLD(1)),
+	VSP1_DBFS_REG(VI6_BRU_BLD(2)),
+	VSP1_DBFS_REG(VI6_BRU_BLD(3)),
+	VSP1_DBFS_REG(VI6_BRU_BLD(4)),
+
+	VSP1_DBFS_REG(VI6_BRU_ROP),
+
+	VSP1_DBFS_REG(VI6_HGO_OFFSET),
+	VSP1_DBFS_REG(VI6_HGO_SIZE),
+	VSP1_DBFS_REG(VI6_HGO_MODE),
+	VSP1_DBFS_REG(VI6_HGO_LB_TH),
+	//VSP1_DBFS_REG(VI6_HGO_R_HISTO(0)),
+	VSP1_DBFS_REG(VI6_HGO_R_MAXMIN),
+	VSP1_DBFS_REG(VI6_HGO_R_SUM),
+	VSP1_DBFS_REG(VI6_HGO_R_LB_DET),
+	//VSP1_DBFS_REG(VI6_HGO_G_HISTO(0)),
+	VSP1_DBFS_REG(VI6_HGO_G_MAXMIN),
+	VSP1_DBFS_REG(VI6_HGO_G_SUM),
+	VSP1_DBFS_REG(VI6_HGO_G_LB_DET),
+	//VSP1_DBFS_REG(VI6_HGO_B_HISTO(0)),
+	VSP1_DBFS_REG(VI6_HGO_B_MAXMIN),
+	VSP1_DBFS_REG(VI6_HGO_B_SUM),
+	VSP1_DBFS_REG(VI6_HGO_B_LB_DET),
+	VSP1_DBFS_REG(VI6_HGO_REGRST),
+
+	VSP1_DBFS_REG(VI6_HGT_OFFSET),
+	VSP1_DBFS_REG(VI6_HGT_SIZE),
+	VSP1_DBFS_REG(VI6_HGT_MODE),
+	VSP1_DBFS_REG(VI6_HGT_LB_TH),
+	VSP1_DBFS_REG(VI6_HGT_MAXMIN),
+	VSP1_DBFS_REG(VI6_HGT_SUM),
+	VSP1_DBFS_REG(VI6_HGT_LB_DET),
+	VSP1_DBFS_REG(VI6_HGT_REGRST),
+
+	VSP1_DBFS_REG(VI6_LIF_CTRL),
+	VSP1_DBFS_REG(VI6_LIF_CSBTH),
+	VSP1_DBFS_REG(VI6_SECURITY_CTRL0),
+	VSP1_DBFS_REG(VI6_SECURITY_CTRL1),
+	VSP1_DBFS_REG(VI6_IP_VERSION),
+	/* VSP-D's don't have this and will segfault if you try to read them */
+	//VSP1_DBFS_REG(VI6_CLUT_TABLE),
+	//VSP1_DBFS_REG(VI6_LUT_TABLE),
+	//VSP1_DBFS_REG(VI6_CLU_ADDR),
+	//VSP1_DBFS_REG(VI6_CLU_DATA),
+};
+
+/*
+ * vsp1_reg_to_name
+ *
+ * Find the name of the register which matches the offset given.
+ * This function assumes that the regset has only unique offsets
+ * in the table.
+ */
+char *vsp1_reg_to_name(u32 offset)
+{
+	unsigned int i;
+	static char notfound[16];
+
+	for (i = 0; i < ARRAY_SIZE(vsp1_regset); i++)
+		if (vsp1_regset[i].offset == offset)
+			return vsp1_regset[i].name;
+
+	snprintf(notfound, sizeof(notfound), "<0x%08x>", offset);
+	return notfound;
+}
+
+/*
+ * vsp1_reg_decode
+ *
+ * Find the name of the register which matches the offset given.
+ * This function assumes that the regset has only unique offsets
+ * in the table.
+ */
+static int vsp1_reg_decode(struct seq_file *s, u32 offset, u32 value)
+{
+	unsigned int i;
+	const struct debugfs_reg32 *reg = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(vsp1_regset); i++)
+		if (vsp1_regset[i].offset == offset) {
+			reg = &vsp1_regset[i];
+			break;
+		}
+
+	if (reg) {
+		seq_printf(s, "%0x08x : %s", value, reg->name);
+		if (reg->decode_reg)
+			reg->decode_reg(s, value);
+		seq_puts(s, "\n");
+	} else {
+		seq_printf(s, "%0x08x : <0x%08x not found>\n", value, offset);
+	}
+
+	return 0;
+}
+
+/*
+ * vsp1_reg_read_and_decode
+ *
+ * Read a register, and if available decode the value into a seq_buffer.
+ * Returns the value, and decode using seq_printf formatting, or just the value
+ * to the string buffer if no decoding is available.
+ */
+static void vsp1_reg_read_and_decode(struct vsp1_device *vsp1,
+				     struct seq_file *s,
+				     struct debugfs_reg32 *reg)
+{
+	u32 value = vsp1_read(vsp1, reg->offset);
+
+	if (reg->decode_reg)
+		return reg->decode_reg(s, value);
+
+	return seq_printf(s, "0x%08x", value);
+}
+
+/* -----------------------------------------------------------------------------
+ * Debugfs management
+ */
+
+static void vsp1_debugfs_print_vsp1_pipe(struct seq_file *seq,
+					 struct vsp1_pipeline *pipe, char *msg)
+{
+
+	if (!pipe) {
+		seq_printf(seq, "No Pipe @ %p : %s\n", pipe, msg);
+
+		return;
+	}
+
+	seq_printf(seq,	"%s Pipe %s\n", msg,
+			pipe->state == VSP1_PIPELINE_STOPPED ? "Stopped" :
+			pipe->state == VSP1_PIPELINE_STOPPING ? "Stopping" :
+			pipe->state == VSP1_PIPELINE_RUNNING ? "Running" : "X");
+
+	seq_printf(seq,	"stream_count: %d\n"
+			"buffers_ready: %d\n"
+			"sequence: %d\n"
+			"num_inputs: %d\n"
+			"partitions: %d\n",
+			pipe->stream_count,
+			pipe->buffers_ready,
+			pipe->sequence,
+			pipe->num_inputs,
+			pipe->partitions);
+
+}
+
+static int vsp1_debugfs_info(struct seq_file *s, void *p)
+{
+	struct vsp1_device *vsp1 = s->private;
+	unsigned int i;
+	u32 status;
+
+	/* Make sure all reads are with 'powered' device */
+	vsp1_device_get(vsp1);
+
+	seq_printf(s, "name: %s\n", vsp1->info->model ? vsp1->info->model : "");
+
+	status = vsp1_read(vsp1, VI6_STATUS);
+	seq_printf(s, "VI6_STATUS = 0x%08x : ", status);
+	decode_vi6_status(s, status);
+	seq_puts(s, "\n");
+
+	seq_printf(s, "VI6_WPF0_FRCNT = 0x%08x", vsp1_read(vsp1, VI6_WPF0_FRCNT));
+
+	for (i = 0; i < vsp1->info->wpf_count; ++i) {
+		struct vsp1_rwpf *wpf = vsp1->wpf[i];
+		u32 status;
+		u32 enable;
+
+		if (wpf == NULL)
+			continue;
+
+		enable = vsp1_read(vsp1, VI6_WPF_IRQ_ENB(i));
+		status = vsp1_read(vsp1, VI6_WPF_IRQ_STA(i));
+
+		seq_printf(s, "VI6_WPF_IRQ_ENB(%d) = ", i);
+		decode_vi6_wpf_enb(s, enable);
+		seq_puts(s, "\n");
+
+		seq_printf(s, "VI6_WPF_IRQ_STA(%d) = ", i);
+		decode_vi6_wpf_sta(s, status);
+		seq_puts(s, "\n");
+
+		seq_printf(s, "WPF[%d]->entity->Pipe = %p\n", i, wpf->entity.pipe);
+		/* Report the WPF Pipe information */
+		vsp1_debugfs_print_vsp1_pipe(s, wpf->entity.pipe, "WPF");
+
+		status = vsp1_read(vsp1, VI6_DISP_IRQ_STA(i));
+		seq_printf(s, "VI6_DISP_IRQ_STA(%d) = ", i);
+		decode_vi6_disp_irq_sta(s, status);
+		seq_puts(s, "\n");
+	}
+
+	for (i = 0; i < vsp1->info->rpf_count; ++i) {
+		struct vsp1_rwpf *rpf = vsp1->rpf[i];
+
+		if (rpf == NULL)
+			continue;
+
+		seq_printf(s,
+			"RPF[%d]->entity.pipe = %p\n", i, rpf->entity.pipe);
+
+		vsp1_debugfs_print_vsp1_pipe(s, rpf->entity.pipe, "RPF");
+
+	}
+
+	vsp1_device_put(vsp1);
+
+	return 0;
+}
+DEBUGFS_RO_ATTR(vsp1_debugfs_info);
+
+static int vsp1_debugfs_regs(struct seq_file *s, void *p)
+{
+	struct vsp1_device *vsp1 = s->private;
+	unsigned int i;
+	u32 status;
+
+	/* Make sure all reads are with 'powered' device */
+	vsp1_device_get(vsp1);
+
+	for (i = 0; i < ARRAY_SIZE(vsp1_regset); i++) {
+		const struct debugfs_reg32 *reg = &vsp1_regset[i];
+
+		status = vsp1_read(vsp1, reg->offset);
+
+		seq_printf(s, "0x%08x [%s]\n", status, reg->name);
+	}
+
+	vsp1_device_put(vsp1);
+
+	return 0;
+}
+DEBUGFS_RO_ATTR(vsp1_debugfs_regs);
+
+static int vsp1_debugfs_reset_wpf(struct seq_file *s, void *p)
+{
+	struct vsp1_device *vsp1 = s->private;
+	int ret;
+
+	/* Make sure all reads are with 'powered' device */
+	vsp1_device_get(vsp1);
+
+	/* Prints are 'before' and 'after' to preserve timing on output */
+	seq_puts(s, "Resetting WPF[0] : ");
+
+	ret = vsp1_reset_wpf(vsp1->wpf[0]->entity.vsp1,
+			     vsp1->wpf[0]->entity.index);
+	if (ret == 0)
+		seq_puts(s, "Success\n");
+	else
+		seq_puts(s, "Failed\n");
+
+	vsp1_device_put(vsp1);
+
+	return 0;
+}
+DEBUGFS_RO_ATTR(vsp1_debugfs_reset_wpf);
+
+/* Debugfs initialised after entities are created */
+int vsp1_debugfs_init(struct vsp1_device *vsp1)
+{
+	struct dentry *info_file;
+
+	vsp1->regset.regs = vsp1_regset;
+	vsp1->regset.base = vsp1->mmio;
+	vsp1->regset.nregs = ARRAY_SIZE(vsp1_regset);
+
+	vsp1->dbgroot = debugfs_create_dir(dev_name(vsp1->dev), NULL);
+	if (!vsp1->dbgroot)
+		return -ENOMEM;
+
+	/* dentry pointer discarded */
+	info_file = debugfs_create_file("info", 0444,
+						 vsp1->dbgroot,
+						 vsp1,
+						 &vsp1_debugfs_info_fops);
+
+	/* dentry pointer discarded */
+	info_file = debugfs_create_file("regs_local", 0444,
+						 vsp1->dbgroot,
+						 vsp1,
+						 &vsp1_debugfs_regs_fops);
+
+	/* dentry pointer discarded */
+	info_file = debugfs_create_file("reset_wpf0", 0444,
+						 vsp1->dbgroot,
+						 vsp1,
+						 &vsp1_debugfs_reset_wpf_fops);
+
+	debugfs_create_regset32("regs", 0444, vsp1->dbgroot, &vsp1->regset);
+
+	return 0;
+}
+
+void vsp1_debugfs_remove(struct vsp1_device *vsp1)
+{
+	debugfs_remove_recursive(vsp1->dbgroot);
+	vsp1_device_put(vsp1);
+}
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_debugfs.h b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.h
new file mode 100644
index 000000000000..c2a7f232ed44
--- /dev/null
+++ b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.h
@@ -0,0 +1,49 @@
+/*
+ * vsp1_debugfs.h  --  R-Car VSP1 DebugFS system
+ *
+ * Copyright (C) 2016 Renesas Corporation
+ *
+ * Contact: Kieran Bingham (kieran.bingham@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __VSP1_DEBUGFS_H__
+#define __VSP1_DEBUGFS_H__
+
+/*
+ * Helper for creating seq_file operations
+ */
+#define DEBUGFS_RO_ATTR(name) \
+	static int name##_open(struct inode *inode, struct file *file) \
+	{ return single_open(file, name, inode->i_private); }      \
+	static const struct file_operations name##_fops = { \
+		.owner = THIS_MODULE, \
+		.open = name##_open, \
+		.llseek = seq_lseek, \
+		.read = seq_read, \
+		.release = single_release \
+	}
+
+#ifdef CONFIG_DEBUG_FS
+int vsp1_debugfs_init(struct vsp1_device *vsp1);
+void vsp1_debugfs_remove(struct vsp1_device *vsp1);
+char *vsp1_reg_to_name(u32 offset);
+#else
+static inline int vsp1_debugfs_init(struct vsp1_device *vsp1)
+{
+	return 0;
+}
+
+static inline void vsp1_debugfs_remove(struct vsp1_device *vsp1) { };
+
+static inline char *vsp1_reg_to_name(u32 offset)
+{
+	return "<>";
+}
+#endif /* CONFIG_DEBUG_FS */
+
+#endif /* __VSP1_DEBUGFS_H__ */
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_drv.c b/drivers/media/platform/renesas/vsp1/vsp1_drv.c
index 392aced46758..29434dcd16b4 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_drv.c
@@ -24,6 +24,7 @@
 #include "vsp1.h"
 #include "vsp1_brx.h"
 #include "vsp1_clu.h"
+#include "vsp1_debugfs.h"
 #include "vsp1_dl.h"
 #include "vsp1_drm.h"
 #include "vsp1_hgo.h"
@@ -897,6 +898,9 @@ static int vsp1_probe(struct platform_device *pdev)
 		goto done;
 	}
 
+	/* Register Debug File System before entities. */
+	vsp1_debugfs_init(vsp1);
+
 	/* Instantiate entities. */
 	ret = vsp1_create_entities(vsp1);
 	if (ret < 0) {
@@ -918,6 +922,7 @@ static int vsp1_remove(struct platform_device *pdev)
 	struct vsp1_device *vsp1 = platform_get_drvdata(pdev);
 
 	vsp1_destroy_entities(vsp1);
+	vsp1_debugfs_remove(vsp1);
 	rcar_fcp_put(vsp1->fcp);
 
 	pm_runtime_disable(&pdev->dev);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/7] v4l: vsp1: Add CLK_CTRL and MRESET register definitions
  2022-06-29 10:51 [PATCH 0/7] renesas: vsp1: debugfs facility Kieran Bingham
                   ` (2 preceding siblings ...)
  2022-06-29 10:51 ` [PATCH 3/7] v4l: vsp1: Add debugfs system v1.8 Kieran Bingham
@ 2022-06-29 10:51 ` Kieran Bingham
  2022-06-29 10:51 ` [PATCH 5/7] v4l: vsp1: Add safety mechanism registers Kieran Bingham
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kieran Bingham @ 2022-06-29 10:51 UTC (permalink / raw)
  To: linux-renesas-soc, linux-media, Eugeniu Rosca
  Cc: Laurent Pinchart, Kieran Bingham

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
---
 .../media/platform/renesas/vsp1/vsp1_debugfs.c   | 10 ++++++++++
 drivers/media/platform/renesas/vsp1/vsp1_regs.h  | 16 ++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
index 4e361fd4c445..3bae9556f38b 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
@@ -107,10 +107,20 @@ static const struct debugfs_reg32 vsp1_regset[] = {
 	VSP1_DBFS_REG(VI6_CMD(0)),
 	VSP1_DBFS_REG(VI6_CMD(1)),
 
+	VSP1_DBFS_REG(VI6_CLK_CTRL0),
+	VSP1_DBFS_REG(VI6_CLK_CTRL1),
+
 	VSP1_DBFS_REG(VI6_CLK_DCSWT),
 
+	VSP1_DBFS_REG(VI6_CLK_DCSM0),
+	VSP1_DBFS_REG(VI6_CLK_DCSM1),
+
 	VSP1_DBFS_REG(VI6_SRESET),
 
+	VSP1_DBFS_REG(VI6_MRESET_ENB0),
+	VSP1_DBFS_REG(VI6_MRESET_ENB1),
+	VSP1_DBFS_REG(VI6_MRESET),
+
 	VSP1_DBFS_REG_DECODE(VI6_STATUS, decode_vi6_status),
 
 	VSP1_DBFS_REG_DECODE(VI6_WPF_IRQ_ENB(0), decode_vi6_wpf_enb),
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_regs.h b/drivers/media/platform/renesas/vsp1/vsp1_regs.h
index 632c43bb4cbd..86855b34dcaf 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/renesas/vsp1/vsp1_regs.h
@@ -18,15 +18,31 @@
 #define VI6_CMD_UPDHDR			BIT(4)
 #define VI6_CMD_STRCMD			BIT(0)
 
+#define VI6_CLK_CTRL0			0x0010
+#define VI6_CLK_CTRL1			0x0014
+
 #define VI6_CLK_DCSWT			0x0018
 #define VI6_CLK_DCSWT_CSTPW_MASK	(0xff << 8)
 #define VI6_CLK_DCSWT_CSTPW_SHIFT	8
 #define VI6_CLK_DCSWT_CSTRW_MASK	(0xff << 0)
 #define VI6_CLK_DCSWT_CSTRW_SHIFT	0
 
+#define VI6_CLK_DCSM0			0x001c
+#define VI6_CLK_DCSM1			0x0020
+
 #define VI6_SRESET			0x0028
 #define VI6_SRESET_SRTS(n)		BIT(n)
 
+#define VI6_MRESET_ENB0			0x002c
+#define VI6_MRESET_ENB0_RESET		0x0000001f
+#define VI6_MRESET_ENB0_RESET_BUS	0x30000f1f
+
+#define VI6_MRESET_ENB1			0x0030
+#define VI6_MRESET_ENB1_RESET		0xff00ffff
+
+#define VI6_MRESET			0x0034
+#define VI6_MRESET_MRST			BIT(0)
+
 #define VI6_STATUS			0x0038
 #define VI6_STATUS_FLD_STD(n)		BIT((n) + 28)
 #define VI6_STATUS_SYS_ACT(n)		BIT((n) + 8)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/7] v4l: vsp1: Add safety mechanism registers
  2022-06-29 10:51 [PATCH 0/7] renesas: vsp1: debugfs facility Kieran Bingham
                   ` (3 preceding siblings ...)
  2022-06-29 10:51 ` [PATCH 4/7] v4l: vsp1: Add CLK_CTRL and MRESET register definitions Kieran Bingham
@ 2022-06-29 10:51 ` Kieran Bingham
  2022-06-29 10:51 ` [PATCH 6/7] v4l: vsp1: Provide video node debugfs entries Kieran Bingham
  2022-06-29 10:51 ` [PATCH 7/7] v4l: vsp1: debugfs: Add DLM directory Kieran Bingham
  6 siblings, 0 replies; 8+ messages in thread
From: Kieran Bingham @ 2022-06-29 10:51 UTC (permalink / raw)
  To: linux-renesas-soc, linux-media, Eugeniu Rosca
  Cc: Laurent Pinchart, Kieran Bingham

Provide the Safety Mechanism registers so that they can be reported
through debugfs

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
---
 .../media/platform/renesas/vsp1/vsp1_debugfs.c |  6 ++++++
 .../media/platform/renesas/vsp1/vsp1_regs.h    | 18 ++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
index 3bae9556f38b..0340acd3209b 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
@@ -121,6 +121,12 @@ static const struct debugfs_reg32 vsp1_regset[] = {
 	VSP1_DBFS_REG(VI6_MRESET_ENB1),
 	VSP1_DBFS_REG(VI6_MRESET),
 
+	VSP1_DBFS_REG(VI6_WPF0_WDT),
+	VSP1_DBFS_REG(VI6_WPF0_FRCNT),
+	VSP1_DBFS_REG(VI6_ECM0_IRQ_ENB),
+	VSP1_DBFS_REG(VI6_ECM0_IRQ_STA),
+	VSP1_DBFS_REG(VI6_CTL_ERRINJ),
+
 	VSP1_DBFS_REG_DECODE(VI6_STATUS, decode_vi6_status),
 
 	VSP1_DBFS_REG_DECODE(VI6_WPF_IRQ_ENB(0), decode_vi6_wpf_enb),
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_regs.h b/drivers/media/platform/renesas/vsp1/vsp1_regs.h
index 86855b34dcaf..f90a01a21b06 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/renesas/vsp1/vsp1_regs.h
@@ -70,6 +70,24 @@
 #define VI6_WPF_LINE_COUNT(n)		(0x0084 + (n) * 4)
 #define VI6_WPF_LINE_COUNT_MASK		(0x1fffff << 0)
 
+/* Safety Mechanism */
+#define VI6_WPF0_WDT			0x00c4
+#define VI6_WPF0_WDT_WDTEN		BIT(16)
+#define VI6_WPF0_TIMER_CYC_MASK		(0xffff << 0)
+
+#define VI6_WPF0_FRCNT			0x00d4
+#define VI6_WPF0_FRCNT_MASK		(0xfff << 0)
+
+#define VI6_ECM0_IRQ_ENB		0x00dc
+#define VI6_ECM0_IRQ_ENB_W0ALME		BIT(24)
+#define VI6_ECM0_IRQ_ENB_RRSP0E		BIT(0)
+
+#define VI6_ECM0_IRQ_STA		0x00e0
+#define VI6_ECM0_IRQ_STA_W0ALM		BIT(24)
+#define VI6_ECM0_IRQ_STA_RRSP0		BIT(0)
+
+#define VI6_CTL_ERRINJ			0x00e8
+
 /* -----------------------------------------------------------------------------
  * Display List Control Registers
  */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 6/7] v4l: vsp1: Provide video node debugfs entries
  2022-06-29 10:51 [PATCH 0/7] renesas: vsp1: debugfs facility Kieran Bingham
                   ` (4 preceding siblings ...)
  2022-06-29 10:51 ` [PATCH 5/7] v4l: vsp1: Add safety mechanism registers Kieran Bingham
@ 2022-06-29 10:51 ` Kieran Bingham
  2022-06-29 10:51 ` [PATCH 7/7] v4l: vsp1: debugfs: Add DLM directory Kieran Bingham
  6 siblings, 0 replies; 8+ messages in thread
From: Kieran Bingham @ 2022-06-29 10:51 UTC (permalink / raw)
  To: linux-renesas-soc, linux-media, Eugeniu Rosca
  Cc: Laurent Pinchart, Kieran Bingham

Expose a debugfs file for each video node such that useful statistics
and performance metrics can be identified

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
---
 drivers/media/platform/renesas/vsp1/vsp1.h    |  1 +
 .../platform/renesas/vsp1/vsp1_debugfs.c      | 39 +++++++++++++++++++
 .../platform/renesas/vsp1/vsp1_debugfs.h      |  8 ++++
 .../media/platform/renesas/vsp1/vsp1_video.c  | 14 ++++++-
 .../media/platform/renesas/vsp1/vsp1_video.h  |  9 +++++
 5 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/renesas/vsp1/vsp1.h b/drivers/media/platform/renesas/vsp1/vsp1.h
index 1951d350b60a..774f006d9b6a 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1.h
+++ b/drivers/media/platform/renesas/vsp1/vsp1.h
@@ -38,6 +38,7 @@ struct vsp1_rwpf;
 struct vsp1_sru;
 struct vsp1_uds;
 struct vsp1_uif;
+struct vsp1_video;
 
 #define VSP1_MAX_LIF		2
 #define VSP1_MAX_RPF		5
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
index 0340acd3209b..fbee914de47c 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.c
@@ -17,6 +17,7 @@
 #include "vsp1.h"
 #include "vsp1_rwpf.h"
 #include "vsp1_pipe.h"
+#include "vsp1_video.h"
 
 #include "vsp1_debugfs.h"
 
@@ -522,3 +523,41 @@ void vsp1_debugfs_remove(struct vsp1_device *vsp1)
 	debugfs_remove_recursive(vsp1->dbgroot);
 	vsp1_device_put(vsp1);
 }
+
+
+/*
+ * VSP1 Video Debugfs nodes
+ */
+static int vsp1_video_stats(struct seq_file *s, void *p)
+{
+	struct vsp1_video *video = s->private;
+
+	seq_puts(s, "Reading from a struct vsp1_video node\n");
+
+	seq_printf(s,	" buffer_queued %d\n"
+			" buffer_done %d\n"
+			" buffer_failed %d\n",
+			video->statistics.buffer_queued,
+			video->statistics.buffer_done,
+			video->statistics.buffer_failed);
+
+	return 0;
+}
+
+DEBUGFS_RO_ATTR(vsp1_video_stats);
+
+void vsp1_debugfs_create_video_stats(struct vsp1_video *video, const char *name)
+{
+	struct vsp1_device *vsp1 = video->vsp1;
+
+	/* dentry pointer discarded */
+	video->debugfs_file = debugfs_create_file(name,
+					0444, vsp1->dbgroot, video,
+					&vsp1_video_stats_fops);
+}
+
+void vsp1_debugfs_cleanup_video_stats(struct vsp1_video *video)
+{
+	debugfs_remove(video->debugfs_file);
+	video->debugfs_file = NULL;
+}
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_debugfs.h b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.h
index c2a7f232ed44..2a6aac0a5940 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_debugfs.h
+++ b/drivers/media/platform/renesas/vsp1/vsp1_debugfs.h
@@ -32,6 +32,10 @@
 int vsp1_debugfs_init(struct vsp1_device *vsp1);
 void vsp1_debugfs_remove(struct vsp1_device *vsp1);
 char *vsp1_reg_to_name(u32 offset);
+
+void vsp1_debugfs_create_video_stats(struct vsp1_video *video,
+		const char *name);
+void vsp1_debugfs_cleanup_video_stats(struct vsp1_video *video);
 #else
 static inline int vsp1_debugfs_init(struct vsp1_device *vsp1)
 {
@@ -44,6 +48,10 @@ static inline char *vsp1_reg_to_name(u32 offset)
 {
 	return "<>";
 }
+
+static inline vsp1_debugfs_create_video_stats(struct vsp1_video *video,
+		const char *name) { };
+static inline vsp1_debugfs_cleanup_video_stats(struct vsp1_video *video) { };
 #endif /* CONFIG_DEBUG_FS */
 
 #endif /* __VSP1_DEBUGFS_H__ */
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_video.c b/drivers/media/platform/renesas/vsp1/vsp1_video.c
index 51219b1b6ea9..813be13bb84b 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_video.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_video.c
@@ -25,6 +25,7 @@
 
 #include "vsp1.h"
 #include "vsp1_brx.h"
+#include "vsp1_debugfs.h"
 #include "vsp1_dl.h"
 #include "vsp1_entity.h"
 #include "vsp1_hgo.h"
@@ -342,6 +343,7 @@ vsp1_video_complete_buffer(struct vsp1_video *video)
 		vb2_set_plane_payload(&done->buf.vb2_buf, i,
 				      vb2_plane_size(&done->buf.vb2_buf, i));
 	vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE);
+	video->statistics.buffer_done++;
 
 	return next;
 }
@@ -768,6 +770,8 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb)
 	list_add_tail(&buf->queue, &video->irqqueue);
 	spin_unlock_irqrestore(&video->irqlock, flags);
 
+	video->statistics.buffer_queued++;
+
 	if (!empty)
 		return;
 
@@ -839,8 +843,10 @@ static void vsp1_video_release_buffers(struct vsp1_video *video)
 
 	/* Remove all buffers from the IRQ queue. */
 	spin_lock_irqsave(&video->irqlock, flags);
-	list_for_each_entry(buffer, &video->irqqueue, queue)
+	list_for_each_entry(buffer, &video->irqqueue, queue) {
 		vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR);
+		video->statistics.buffer_failed++;
+	}
 	INIT_LIST_HEAD(&video->irqqueue);
 	spin_unlock_irqrestore(&video->irqlock, flags);
 }
@@ -1310,6 +1316,9 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
 		goto error;
 	}
 
+	/* Create a Video debugfs node */
+	vsp1_debugfs_create_video_stats(video, video->video.name);
+
 	return video;
 
 error:
@@ -1319,6 +1328,9 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
 
 void vsp1_video_cleanup(struct vsp1_video *video)
 {
+	/* Remove any debugfs entries */
+	vsp1_debugfs_cleanup_video_stats(video);
+
 	if (video_is_registered(&video->video))
 		video_unregister_device(&video->video);
 
diff --git a/drivers/media/platform/renesas/vsp1/vsp1_video.h b/drivers/media/platform/renesas/vsp1/vsp1_video.h
index f3cf5e2fdf5a..a9499822c7d6 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_video.h
+++ b/drivers/media/platform/renesas/vsp1/vsp1_video.h
@@ -28,6 +28,12 @@ to_vsp1_vb2_buffer(struct vb2_v4l2_buffer *vbuf)
 	return container_of(vbuf, struct vsp1_vb2_buffer, buf);
 }
 
+struct vsp1_video_stats {
+	u32 buffer_queued;
+	u32 buffer_done;
+	u32 buffer_failed;
+};
+
 struct vsp1_video {
 	struct list_head list;
 	struct vsp1_device *vsp1;
@@ -44,6 +50,9 @@ struct vsp1_video {
 	struct vb2_queue queue;
 	spinlock_t irqlock;
 	struct list_head irqqueue;
+
+	struct dentry *debugfs_file;
+	struct vsp1_video_stats statistics;
 };
 
 static inline struct vsp1_video *to_vsp1_video(struct video_device *vdev)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 7/7] v4l: vsp1: debugfs: Add DLM directory
  2022-06-29 10:51 [PATCH 0/7] renesas: vsp1: debugfs facility Kieran Bingham
                   ` (5 preceding siblings ...)
  2022-06-29 10:51 ` [PATCH 6/7] v4l: vsp1: Provide video node debugfs entries Kieran Bingham
@ 2022-06-29 10:51 ` Kieran Bingham
  6 siblings, 0 replies; 8+ messages in thread
From: Kieran Bingham @ 2022-06-29 10:51 UTC (permalink / raw)
  To: linux-renesas-soc, linux-media, Eugeniu Rosca
  Cc: Laurent Pinchart, Kieran Bingham

Provide the ability to output a display list in use over debugfs.

In the event that the hardware has hung, it should be possible to
identify the current/most recent display list written to hardware by
viewing the DLM->active file:

 cat /debugfs/fe9a0000.vsp/DLM/active

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

--
2021-05-05:
 - Don't store dentry pointers which are not used

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
---
 drivers/media/platform/renesas/vsp1/vsp1_dl.c | 107 ++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/drivers/media/platform/renesas/vsp1/vsp1_dl.c b/drivers/media/platform/renesas/vsp1/vsp1_dl.c
index ad3fa1c9cc73..f75ecc5b485e 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_dl.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_dl.c
@@ -17,6 +17,8 @@
 #include "vsp1.h"
 #include "vsp1_dl.h"
 
+#include "vsp1_debugfs.h"
+
 #define VSP1_DL_NUM_ENTRIES		256
 
 #define VSP1_DLH_INT_ENABLE		(1 << 1)
@@ -226,6 +228,8 @@ struct vsp1_dl_manager {
 
 	struct vsp1_dl_body_pool *pool;
 	struct vsp1_dl_cmd_pool *cmdpool;
+
+	struct dentry *dbgroot;
 };
 
 /* -----------------------------------------------------------------------------
@@ -1086,6 +1090,105 @@ struct vsp1_dl_body *vsp1_dlm_dl_body_get(struct vsp1_dl_manager *dlm)
 	return vsp1_dl_body_get(dlm->pool);
 }
 
+/* -----------------------------------------------------------------------------
+ * Debugfs internal views
+ */
+
+static void seq_print_list_body(struct seq_file *s, struct vsp1_dl_body *dlb)
+{
+	int i;
+
+	for (i = 0; i < dlb->num_entries; i++) {
+		struct vsp1_dl_entry *e = &dlb->entries[i];
+
+		seq_printf(s, "0x%08x -> %s\n", e->data,
+			   vsp1_reg_to_name(e->addr));
+	}
+}
+
+static void seq_printf_dl(struct seq_file *s, struct vsp1_dl_list *dl)
+{
+	struct vsp1_dl_body *dlb;
+	struct vsp1_dl_list *child;
+
+	if (!dl)
+		return;
+
+	seq_print_list_body(s, dl->body0);
+
+	list_for_each_entry(dlb, &dl->bodies, list)
+		seq_print_list_body(s, dlb);
+
+	if (dl->has_chain)
+		list_for_each_entry(child, &dl->chain, chain)
+			seq_print_list_body(s, child->body0);
+}
+
+static int vsp1_debugfs_dlm_active(struct seq_file *s, void *p)
+{
+	struct vsp1_dl_manager *dlm = s->private;
+
+	seq_printf_dl(s, dlm->active);
+
+	return 0;
+}
+
+DEBUGFS_RO_ATTR(vsp1_debugfs_dlm_active);
+
+static int vsp1_debugfs_dlm_pending(struct seq_file *s, void *p)
+{
+	struct vsp1_dl_manager *dlm = s->private;
+
+	seq_printf_dl(s, dlm->pending);
+
+	return 0;
+}
+
+DEBUGFS_RO_ATTR(vsp1_debugfs_dlm_pending);
+
+static int vsp1_debugfs_dlm_queued(struct seq_file *s, void *p)
+{
+	struct vsp1_dl_manager *dlm = s->private;
+
+	seq_printf_dl(s, dlm->queued);
+
+	return 0;
+}
+
+DEBUGFS_RO_ATTR(vsp1_debugfs_dlm_queued);
+
+/* Debugfs initialised after entities are created */
+static int vsp1_debugfs_init_dlm(struct vsp1_dl_manager *dlm)
+{
+	struct vsp1_device *vsp1 = dlm->vsp1;
+
+	dlm->dbgroot = debugfs_create_dir("DLM", vsp1->dbgroot);
+	if (!dlm->dbgroot)
+		return -ENOMEM;
+
+	/* dentry pointers discarded */
+	debugfs_create_file("active", 0444, dlm->dbgroot, dlm,
+			    &vsp1_debugfs_dlm_active_fops);
+
+	debugfs_create_file("pending", 0444, dlm->dbgroot, dlm,
+			    &vsp1_debugfs_dlm_pending_fops);
+
+	debugfs_create_file("queued", 0444, dlm->dbgroot, dlm,
+			    &vsp1_debugfs_dlm_queued_fops);
+
+	return 0;
+}
+
+static void vsp1_debugfs_destroy_dlm(struct vsp1_dl_manager *dlm)
+{
+	debugfs_remove(dlm->dbgroot);
+	dlm->dbgroot = NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * Object creation and destruction
+ */
+
 struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
 					unsigned int index,
 					unsigned int prealloc)
@@ -1149,6 +1252,8 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
 		}
 	}
 
+	vsp1_debugfs_init_dlm(dlm);
+
 	return dlm;
 }
 
@@ -1159,6 +1264,8 @@ void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm)
 	if (!dlm)
 		return;
 
+	vsp1_debugfs_destroy_dlm(dlm);
+
 	list_for_each_entry_safe(dl, next, &dlm->free, list) {
 		list_del(&dl->list);
 		vsp1_dl_list_free(dl);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-06-29 10:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-29 10:51 [PATCH 0/7] renesas: vsp1: debugfs facility Kieran Bingham
2022-06-29 10:51 ` [PATCH 1/7] debugfs: Extend debugfs regset to support register decoding Kieran Bingham
2022-06-29 10:51 ` [PATCH 2/7] v4l: vsp1: Provide WPF underflow error detection and reporting Kieran Bingham
2022-06-29 10:51 ` [PATCH 3/7] v4l: vsp1: Add debugfs system v1.8 Kieran Bingham
2022-06-29 10:51 ` [PATCH 4/7] v4l: vsp1: Add CLK_CTRL and MRESET register definitions Kieran Bingham
2022-06-29 10:51 ` [PATCH 5/7] v4l: vsp1: Add safety mechanism registers Kieran Bingham
2022-06-29 10:51 ` [PATCH 6/7] v4l: vsp1: Provide video node debugfs entries Kieran Bingham
2022-06-29 10:51 ` [PATCH 7/7] v4l: vsp1: debugfs: Add DLM directory Kieran Bingham

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.