From 02af10c45f7db337ae14b9c402971472fce7b658 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Mon, 9 Jan 2023 19:12:00 +0800 Subject: [PATCH] PCI: rockchip: dw: Support get_dma_status for polling DMA status 1.Support get_dma_status for polling DMA status 2.Remove the struct of dw_pcie from dmatest Change-Id: Ifef2b9172234e597354d9ae410d3f39be55cc6a8 Signed-off-by: Jon Lin --- drivers/pci/controller/dwc/pcie-dw-dmatest.c | 94 ++----------------- drivers/pci/controller/dwc/pcie-dw-dmatest.h | 7 +- .../pci/controller/dwc/pcie-dw-ep-rockchip.c | 61 +++++++++++- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 +- drivers/pci/controller/rockchip-pcie-dma.h | 1 + 5 files changed, 70 insertions(+), 95 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-dw-dmatest.c b/drivers/pci/controller/dwc/pcie-dw-dmatest.c index 79af779a2e6a..edc9b68eb589 100644 --- a/drivers/pci/controller/dwc/pcie-dw-dmatest.c +++ b/drivers/pci/controller/dwc/pcie-dw-dmatest.c @@ -49,44 +49,10 @@ MODULE_PARM_DESC(test_dev, "Choose dma_obj device,(default 0)"); #define PCIE_DW_MISC_DMATEST_DEV_MAX 5 -#define PCIE_DMA_OFFSET 0x380000 - -#define PCIE_DMA_CTRL_OFF 0x8 -#define PCIE_DMA_WR_ENB 0xc -#define PCIE_DMA_WR_CTRL_LO 0x200 -#define PCIE_DMA_WR_CTRL_HI 0x204 -#define PCIE_DMA_WR_XFERSIZE 0x208 -#define PCIE_DMA_WR_SAR_PTR_LO 0x20c -#define PCIE_DMA_WR_SAR_PTR_HI 0x210 -#define PCIE_DMA_WR_DAR_PTR_LO 0x214 -#define PCIE_DMA_WR_DAR_PTR_HI 0x218 -#define PCIE_DMA_WR_WEILO 0x18 -#define PCIE_DMA_WR_WEIHI 0x1c -#define PCIE_DMA_WR_DOORBELL 0x10 -#define PCIE_DMA_WR_INT_STATUS 0x4c -#define PCIE_DMA_WR_INT_MASK 0x54 -#define PCIE_DMA_WR_INT_CLEAR 0x58 - -#define PCIE_DMA_RD_ENB 0x2c -#define PCIE_DMA_RD_CTRL_LO 0x300 -#define PCIE_DMA_RD_CTRL_HI 0x304 -#define PCIE_DMA_RD_XFERSIZE 0x308 -#define PCIE_DMA_RD_SAR_PTR_LO 0x30c -#define PCIE_DMA_RD_SAR_PTR_HI 0x310 -#define PCIE_DMA_RD_DAR_PTR_LO 0x314 -#define PCIE_DMA_RD_DAR_PTR_HI 0x318 -#define PCIE_DMA_RD_WEILO 0x38 -#define PCIE_DMA_RD_WEIHI 0x3c -#define PCIE_DMA_RD_DOORBELL 0x30 -#define PCIE_DMA_RD_INT_STATUS 0xa0 -#define PCIE_DMA_RD_INT_MASK 0xa8 -#define PCIE_DMA_RD_INT_CLEAR 0xac - #define PCIE_DMA_CHANEL_MAX_NUM 2 struct pcie_dw_dmatest_dev { struct dma_trx_obj *obj; - struct dw_pcie *pci; bool irq_en; struct completion rd_done[PCIE_DMA_CHANEL_MAX_NUM]; @@ -113,55 +79,12 @@ static void pcie_dw_dmatest_show(void) dev_info(s_dmatest_dev[test_dev].obj->dev, " is current test_dev\n"); } -static int rk_pcie_get_dma_status(struct dw_pcie *pci, u8 chn, enum dma_dir dir) -{ - union int_status status; - union int_clear clears; - int ret = 0; - - dev_dbg(pci->dev, "%s %x %x\n", __func__, dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS), - dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS)); - - if (dir == DMA_TO_BUS) { - status.asdword = dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS); - if (status.donesta & BIT(chn)) { - clears.doneclr = 0x1 << chn; - dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_CLEAR, clears.asdword); - ret = 1; - } - - if (status.abortsta & BIT(chn)) { - dev_err(pci->dev, "%s, write abort\n", __func__); - clears.abortclr = 0x1 << chn; - dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_CLEAR, clears.asdword); - ret = -1; - } - } else { - status.asdword = dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS); - - if (status.donesta & BIT(chn)) { - clears.doneclr = 0x1 << chn; - dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_CLEAR, clears.asdword); - ret = 1; - } - - if (status.abortsta & BIT(chn)) { - dev_err(pci->dev, "%s, read abort %x\n", __func__, status.asdword); - clears.abortclr = 0x1 << chn; - dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_CLEAR, clears.asdword); - ret = -1; - } - } - - return ret; -} - -static int rk_pcie_dma_wait_for_finised(struct dma_trx_obj *obj, struct dw_pcie *pci, struct dma_table *table) +static int rk_pcie_dma_wait_for_finised(struct dma_trx_obj *obj, struct dma_table *table) { int ret; do { - ret = rk_pcie_get_dma_status(pci, table->chn, table->dir); + ret = obj->get_dma_status(obj, table->chn, table->dir); } while (!ret); return ret; @@ -172,7 +95,6 @@ static int rk_pcie_dma_frombus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, { struct dma_table *table; struct dma_trx_obj *obj = dmatest_dev->obj; - struct dw_pcie *pci = dmatest_dev->pci; int ret; if (chn >= PCIE_DMA_CHANEL_MAX_NUM) @@ -202,7 +124,7 @@ static int rk_pcie_dma_frombus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, else if (ret == 0) dev_err(obj->dev, "%s timed out\n", __func__); } else { - ret = rk_pcie_dma_wait_for_finised(obj, pci, table); + ret = rk_pcie_dma_wait_for_finised(obj, table); } mutex_unlock(&dmatest_dev->rd_lock[chn]); @@ -216,7 +138,6 @@ static int rk_pcie_dma_tobus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, { struct dma_table *table; struct dma_trx_obj *obj = dmatest_dev->obj; - struct dw_pcie *pci = dmatest_dev->pci; int ret; if (chn >= PCIE_DMA_CHANEL_MAX_NUM) @@ -246,7 +167,7 @@ static int rk_pcie_dma_tobus(struct pcie_dw_dmatest_dev *dmatest_dev, u32 chn, else if (ret == 0) dev_err(obj->dev, "%s timed out\n", __func__); } else { - ret = rk_pcie_dma_wait_for_finised(obj, pci, table); + ret = rk_pcie_dma_wait_for_finised(obj, table); } mutex_unlock(&dmatest_dev->wr_lock[chn]); @@ -270,23 +191,22 @@ static int rk_pcie_dma_interrupt_handler_call_back(struct dma_trx_obj *obj, u32 return 0; } -struct dma_trx_obj *pcie_dw_dmatest_register(struct dw_pcie *pci, bool irq_en) +struct dma_trx_obj *pcie_dw_dmatest_register(struct device *dev, bool irq_en) { struct dma_trx_obj *obj; struct pcie_dw_dmatest_dev *dmatest_dev = &s_dmatest_dev[cur_dmatest_dev]; int i; - obj = devm_kzalloc(pci->dev, sizeof(struct dma_trx_obj), GFP_KERNEL); + obj = devm_kzalloc(dev, sizeof(struct dma_trx_obj), GFP_KERNEL); if (!obj) return ERR_PTR(-ENOMEM); - obj->dev = pci->dev; + obj->dev = dev; obj->priv = dmatest_dev; obj->cb = rk_pcie_dma_interrupt_handler_call_back; /* Save for dmatest */ dmatest_dev->obj = obj; - dmatest_dev->pci = pci; for (i = 0; i < PCIE_DMA_CHANEL_MAX_NUM; i++) { init_completion(&dmatest_dev->rd_done[i]); init_completion(&dmatest_dev->wr_done[i]); diff --git a/drivers/pci/controller/dwc/pcie-dw-dmatest.h b/drivers/pci/controller/dwc/pcie-dw-dmatest.h index 524f5b53f361..cfed7aa22914 100644 --- a/drivers/pci/controller/dwc/pcie-dw-dmatest.h +++ b/drivers/pci/controller/dwc/pcie-dw-dmatest.h @@ -5,10 +5,13 @@ #ifndef __PCIE_DW_DMATEST_H #define __PCIE_DW_DMATEST_H +struct dma_trx_obj; +struct device; + #if IS_ENABLED(CONFIG_PCIE_DW_DMATEST) -struct dma_trx_obj *pcie_dw_dmatest_register(struct dw_pcie *pci, bool irq_en); +struct dma_trx_obj *pcie_dw_dmatest_register(struct device *dev, bool irq_en); #else -static inline struct dma_trx_obj *pcie_dw_dmatest_register(struct dw_pcie *pci, bool irq_en) +static inline struct dma_trx_obj *pcie_dw_dmatest_register(struct device *dev, bool irq_en) { return NULL; } diff --git a/drivers/pci/controller/dwc/pcie-dw-ep-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-ep-rockchip.c index 17cd0818ad75..0fe8714c7b0c 100644 --- a/drivers/pci/controller/dwc/pcie-dw-ep-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-ep-rockchip.c @@ -616,7 +616,7 @@ static irqreturn_t rockchip_pcie_sys_irq_handler(int irq, void *arg) status.asdword = dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS) & (~mask); for (chn = 0; chn < PCIE_DMA_CHANEL_MAX_NUM; chn++) { if (status.donesta & BIT(chn)) { - clears.doneclr = 0x1 << chn; + clears.doneclr = BIT(chn); dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_CLEAR, clears.asdword); if (rockchip->dma_obj && rockchip->dma_obj->cb) @@ -625,7 +625,7 @@ static irqreturn_t rockchip_pcie_sys_irq_handler(int irq, void *arg) if (status.abortsta & BIT(chn)) { dev_err(pci->dev, "%s, abort\n", __func__); - clears.abortclr = 0x1 << chn; + clears.abortclr = BIT(chn); dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_CLEAR, clears.asdword); } @@ -635,7 +635,7 @@ static irqreturn_t rockchip_pcie_sys_irq_handler(int irq, void *arg) status.asdword = dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS) & (~mask); for (chn = 0; chn < PCIE_DMA_CHANEL_MAX_NUM; chn++) { if (status.donesta & BIT(chn)) { - clears.doneclr = 0x1 << chn; + clears.doneclr = BIT(chn); dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_CLEAR, clears.asdword); if (rockchip->dma_obj && rockchip->dma_obj->cb) @@ -644,7 +644,7 @@ static irqreturn_t rockchip_pcie_sys_irq_handler(int irq, void *arg) if (status.abortsta & BIT(chn)) { dev_err(pci->dev, "%s, abort\n", __func__); - clears.abortclr = 0x1 << chn; + clears.abortclr = BIT(chn); dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_CLEAR, clears.asdword); } @@ -702,7 +702,7 @@ static int rockchip_pcie_init_dma_trx(struct rockchip_pcie *rockchip) if (!rockchip_pcie_udma_enabled(rockchip)) return 0; - rockchip->dma_obj = pcie_dw_dmatest_register(pci, true); + rockchip->dma_obj = pcie_dw_dmatest_register(pci->dev, true); if (IS_ERR(rockchip->dma_obj)) { dev_err(rockchip->pci.dev, "failed to prepare dmatest\n"); return -EINVAL; @@ -808,6 +808,56 @@ static void rockchip_pcie_config_dma_dwc(struct dma_table *table) table->start.chnl = table->chn; } +static int rockchip_pcie_get_dma_status(struct dma_trx_obj *obj, u8 chn, enum dma_dir dir) +{ + struct rockchip_pcie *rockchip = dev_get_drvdata(obj->dev); + struct dw_pcie *pci = &rockchip->pci; + union int_status status; + union int_clear clears; + int ret = 0; + + dev_dbg(pci->dev, "%s %x %x\n", __func__, + dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS), + dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS)); + + if (dir == DMA_TO_BUS) { + status.asdword = dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS); + if (status.donesta & BIT(chn)) { + clears.doneclr = BIT(chn); + dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + + PCIE_DMA_WR_INT_CLEAR, clears.asdword); + ret = 1; + } + + if (status.abortsta & BIT(chn)) { + dev_err(pci->dev, "%s, write abort\n", __func__); + clears.abortclr = BIT(chn); + dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + + PCIE_DMA_WR_INT_CLEAR, clears.asdword); + ret = -1; + } + } else { + status.asdword = dw_pcie_readl_dbi(pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS); + + if (status.donesta & BIT(chn)) { + clears.doneclr = BIT(chn); + dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + + PCIE_DMA_RD_INT_CLEAR, clears.asdword); + ret = 1; + } + + if (status.abortsta & BIT(chn)) { + dev_err(pci->dev, "%s, read abort %x\n", __func__, status.asdword); + clears.abortclr = BIT(chn); + dw_pcie_writel_dbi(pci, PCIE_DMA_OFFSET + + PCIE_DMA_RD_INT_CLEAR, clears.asdword); + ret = -1; + } + } + + return ret; +} + static const struct dw_pcie_ops dw_pcie_ops = { .start_link = rockchip_pcie_start_link, .link_up = rockchip_pcie_link_up, @@ -1050,6 +1100,7 @@ already_linkup: if (rockchip->dma_obj) { rockchip->dma_obj->start_dma_func = rockchip_pcie_start_dma_dwc; rockchip->dma_obj->config_dma_func = rockchip_pcie_config_dma_dwc; + rockchip->dma_obj->get_dma_status = rockchip_pcie_get_dma_status; } /* Enable client ELBI interrupt */ diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index a18029fff2b5..f2b67f8a610d 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -853,7 +853,7 @@ static int rk_pcie_init_dma_trx(struct rk_pcie *rk_pcie) goto out; } - rk_pcie->dma_obj = pcie_dw_dmatest_register(rk_pcie->pci, true); + rk_pcie->dma_obj = pcie_dw_dmatest_register(rk_pcie->pci->dev, true); if (IS_ERR(rk_pcie->dma_obj)) { dev_err(rk_pcie->pci->dev, "failed to prepare dmatest\n"); return -EINVAL; diff --git a/drivers/pci/controller/rockchip-pcie-dma.h b/drivers/pci/controller/rockchip-pcie-dma.h index 8ac55f021025..e9da2d0e16ac 100644 --- a/drivers/pci/controller/rockchip-pcie-dma.h +++ b/drivers/pci/controller/rockchip-pcie-dma.h @@ -190,6 +190,7 @@ struct dma_trx_obj { struct pcie_misc_dev *pcie_dev; void (*start_dma_func)(struct dma_trx_obj *obj, struct dma_table *table); void (*config_dma_func)(struct dma_table *table); + int (*get_dma_status)(struct dma_trx_obj *obj, u8 chn, enum dma_dir dir); int (*cb)(struct dma_trx_obj *obj, u32 chn, enum dma_dir dir); ktime_t begin; ktime_t end;