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 <jon.lin@rock-chips.com>
This commit is contained in:
Jon Lin
2023-01-09 19:12:00 +08:00
committed by Tao Huang
parent a3332199c9
commit 02af10c45f
5 changed files with 70 additions and 95 deletions

View File

@@ -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]);

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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;