platform: msm: qcom_geni_se: Add API to dump SE registers

Add an API to dump the SE registers that reflect the state of the SE to
help debug error scenarios.

Change-Id: I2397446c554d446ca9ff542134df15e6de4b1cef
Signed-off-by: Girish Mahadevan <girishm@codeaurora.org>
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index f70dbf2..7264381 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -191,13 +191,6 @@
 
 static void geni_i2c_err(struct geni_i2c_dev *gi2c, int err)
 {
-	u32 m_cmd = readl_relaxed(gi2c->base + SE_GENI_M_CMD0);
-	u32 m_stat = readl_relaxed(gi2c->base + SE_GENI_M_IRQ_STATUS);
-	u32 geni_s = readl_relaxed(gi2c->base + SE_GENI_STATUS);
-	u32 geni_ios = readl_relaxed(gi2c->base + SE_GENI_IOS);
-	u32 dma = readl_relaxed(gi2c->base + SE_GENI_DMA_MODE_EN);
-	u32 rx_st, tx_st;
-
 	if (gi2c->cur)
 		GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
 			    "len:%d, slv-addr:0x%x, RD/WR:%d\n", gi2c->cur->len,
@@ -211,23 +204,9 @@
 		GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s\n",
 			     gi2c_log[err].msg);
 	}
-	if (gi2c->se_mode == GSI_ONLY)
-		goto err_out;
-
-	if (dma) {
-		rx_st = readl_relaxed(gi2c->base + SE_DMA_RX_IRQ_STAT);
-		tx_st = readl_relaxed(gi2c->base + SE_DMA_TX_IRQ_STAT);
-	} else {
-		rx_st = readl_relaxed(gi2c->base + SE_GENI_RX_FIFO_STATUS);
-		tx_st = readl_relaxed(gi2c->base + SE_GENI_TX_FIFO_STATUS);
-	}
-	GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
-		     "DMA:%d tx_stat:0x%x, rx_stat:0x%x, irq-stat:0x%x\n",
-		     dma, tx_st, rx_st, m_stat);
-err_out:
-	GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
-			     "m_cmd:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
-			     m_cmd, geni_s, geni_ios);
+	GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "%s: se-mode:%d\n", __func__,
+							gi2c->se_mode);
+	geni_se_dump_dbg_regs(&gi2c->i2c_rsc, gi2c->base, gi2c->ipcl);
 err_ret:
 	gi2c->err = gi2c_log[err].err;
 }
diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c
index aafb8fc..707c95e 100644
--- a/drivers/platform/msm/qcom-geni-se.c
+++ b/drivers/platform/msm/qcom-geni-se.c
@@ -1247,6 +1247,79 @@
 }
 EXPORT_SYMBOL(geni_se_iommu_free_buf);
 
+/**
+ * geni_se_dump_dbg_regs() - Print relevant registers that capture most
+ *			accurately the state of an SE.
+ * @_dev:		Pointer to the SE's device.
+ * @iomem:		Base address of the SE's register space.
+ * @ipc:		IPC log context handle.
+ *
+ * This function is used to print out all the registers that capture the state
+ * of an SE to help debug any errors.
+ *
+ * Return:	None
+ */
+void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
+				void *ipc)
+{
+	u32 m_cmd0 = 0;
+	u32 m_irq_status = 0;
+	u32 geni_status = 0;
+	u32 geni_ios = 0;
+	u32 dma_rx_irq = 0;
+	u32 dma_tx_irq = 0;
+	u32 rx_fifo_status = 0;
+	u32 tx_fifo_status = 0;
+	u32 se_dma_dbg = 0;
+	u32 m_cmd_ctrl = 0;
+	u32 se_dma_rx_len = 0;
+	u32 se_dma_rx_len_in = 0;
+	u32 se_dma_tx_len = 0;
+	u32 se_dma_tx_len_in = 0;
+	struct geni_se_device *geni_se_dev;
+
+	if (!ipc)
+		return;
+
+	geni_se_dev = dev_get_drvdata(rsc->wrapper_dev);
+	if (unlikely(!geni_se_dev || !geni_se_dev->bus_bw))
+		return;
+	mutex_lock(&geni_se_dev->ab_ib_lock);
+	if (unlikely(list_empty(&rsc->ab_list) || list_empty(&rsc->ib_list))) {
+		GENI_SE_DBG(ipc, false, NULL, "%s: Clocks not on\n", __func__);
+		goto exit_geni_se_dump_dbg_regs;
+	}
+	m_cmd0 = geni_read_reg(base, SE_GENI_M_CMD0);
+	m_irq_status = geni_read_reg(base, SE_GENI_M_IRQ_STATUS);
+	geni_status = geni_read_reg(base, SE_GENI_STATUS);
+	geni_ios = geni_read_reg(base, SE_GENI_IOS);
+	dma_rx_irq = geni_read_reg(base, SE_DMA_TX_IRQ_STAT);
+	dma_tx_irq = geni_read_reg(base, SE_DMA_RX_IRQ_STAT);
+	rx_fifo_status = geni_read_reg(base, SE_GENI_RX_FIFO_STATUS);
+	tx_fifo_status = geni_read_reg(base, SE_GENI_TX_FIFO_STATUS);
+	se_dma_dbg = geni_read_reg(base, SE_DMA_DEBUG_REG0);
+	m_cmd_ctrl = geni_read_reg(base, SE_GENI_M_CMD_CTRL_REG);
+	se_dma_rx_len = geni_read_reg(base, SE_DMA_RX_LEN);
+	se_dma_rx_len_in = geni_read_reg(base, SE_DMA_RX_LEN_IN);
+	se_dma_tx_len = geni_read_reg(base, SE_DMA_TX_LEN);
+	se_dma_tx_len_in = geni_read_reg(base, SE_DMA_TX_LEN_IN);
+
+	GENI_SE_DBG(ipc, false, NULL,
+	"%s: m_cmd0:0x%x, m_irq_status:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
+	__func__, m_cmd0, m_irq_status, geni_status, geni_ios);
+	GENI_SE_DBG(ipc, false, NULL,
+	"dma_rx_irq:0x%x, dma_tx_irq:0x%x, rx_fifo_sts:0x%x, tx_fifo_sts:0x%x\n"
+	, dma_rx_irq, dma_tx_irq, rx_fifo_status, tx_fifo_status);
+	GENI_SE_DBG(ipc, false, NULL,
+	"se_dma_dbg:0x%x, m_cmd_ctrl:0x%x, dma_rxlen:0x%x, dma_rxlen_in:0x%x\n",
+	se_dma_dbg, m_cmd_ctrl, se_dma_rx_len, se_dma_rx_len_in);
+	GENI_SE_DBG(ipc, false, NULL,
+	"dma_txlen:0x%x, dma_txlen_in:0x%x\n", se_dma_tx_len, se_dma_tx_len_in);
+exit_geni_se_dump_dbg_regs:
+	mutex_unlock(&geni_se_dev->ab_ib_lock);
+}
+EXPORT_SYMBOL(geni_se_dump_dbg_regs);
+
 static const struct of_device_id geni_se_dt_match[] = {
 	{ .compatible = "qcom,qupv3-geni-se", },
 	{ .compatible = "qcom,qupv3-geni-se-cb", },
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index aa4c1ed..463785d 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -117,6 +117,7 @@
 #define SE_HW_PARAM_0			(0xE24)
 #define SE_HW_PARAM_1			(0xE28)
 #define SE_DMA_GENERAL_CFG		(0xE30)
+#define SE_DMA_DEBUG_REG0		(0xE40)
 
 /* GENI_OUTPUT_CTRL fields */
 #define DEFAULT_IO_OUTPUT_CTRL_MSK	(GENMASK(6, 0))
@@ -736,6 +737,22 @@
 int geni_se_iommu_free_buf(struct device *wrapper_dev, dma_addr_t *iova,
 			   void *buf, size_t size);
 
+
+/**
+ * geni_se_dump_dbg_regs() - Print relevant registers that capture most
+ *			accurately the state of an SE; meant to be called
+ *			in case of errors to help debug.
+ * @_dev:		Pointer to the SE's device.
+ * @iomem:		Base address of the SE's register space.
+ * @ipc:		IPC log context handle.
+ *
+ * This function is used to print out all the registers that capture the state
+ * of an SE to help debug any errors.
+ *
+ * Return:	None
+ */
+void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
+				void *ipc);
 #else
 static inline unsigned int geni_read_reg_nolog(void __iomem *base, int offset)
 {
@@ -907,5 +924,10 @@
 	return -ENXIO;
 }
 
+void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
+				void *ipc)
+{
+}
+
 #endif
 #endif