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