diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index ec9489fa4e07..5a87275499fa 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -87,6 +87,8 @@ enum rk_pcie_device_mode { #define PCIE_DMA_RD_INT_MASK 0xa8 #define PCIE_DMA_RD_INT_CLEAR 0xac +#define PCIE_DMA_CHANEL_MAX_NUM 2 + /* Parameters for the waiting for iATU enabled routine */ #define LINK_WAIT_IATU_MIN 9000 #define LINK_WAIT_IATU_MAX 10000 @@ -1330,10 +1332,9 @@ static int rk_pcie_reset_grant_ctrl(struct rk_pcie *rk_pcie, return ret; } -static void rk_pcie_start_dma_rd(struct dma_trx_obj *obj, int ctr_off) +static void rk_pcie_start_dma_rd(struct dma_trx_obj *obj, struct dma_table *cur, int ctr_off) { struct rk_pcie *rk_pcie = dev_get_drvdata(obj->dev); - struct dma_table *cur = obj->cur; dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB, cur->enb.asdword); @@ -1355,10 +1356,9 @@ static void rk_pcie_start_dma_rd(struct dma_trx_obj *obj, int ctr_off) cur->start.asdword); } -static void rk_pcie_start_dma_wr(struct dma_trx_obj *obj, int ctr_off) +static void rk_pcie_start_dma_wr(struct dma_trx_obj *obj, struct dma_table *cur, int ctr_off) { struct rk_pcie *rk_pcie = dev_get_drvdata(obj->dev); - struct dma_table *cur = obj->cur; dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB, cur->enb.asdword); @@ -1382,17 +1382,17 @@ static void rk_pcie_start_dma_wr(struct dma_trx_obj *obj, int ctr_off) cur->start.asdword); } -static void rk_pcie_start_dma_dwc(struct dma_trx_obj *obj) +static void rk_pcie_start_dma_dwc(struct dma_trx_obj *obj, struct dma_table *table) { - int dir = obj->cur->dir; - int chn = obj->cur->chn; + int dir = table->dir; + int chn = table->chn; int ctr_off = PCIE_DMA_OFFSET + chn * 0x200; if (dir == DMA_FROM_BUS) - rk_pcie_start_dma_rd(obj, ctr_off); + rk_pcie_start_dma_rd(obj, table, ctr_off); else if (dir == DMA_TO_BUS) - rk_pcie_start_dma_wr(obj, ctr_off); + rk_pcie_start_dma_wr(obj, table, ctr_off); } static void rk_pcie_config_dma_dwc(struct dma_table *table) @@ -1419,76 +1419,50 @@ static void rk_pcie_config_dma_dwc(struct dma_table *table) table->start.chnl = table->chn; } -static inline void -rk_pcie_handle_dma_interrupt(struct rk_pcie *rk_pcie) -{ - struct dma_trx_obj *obj = rk_pcie->dma_obj; - struct dma_table *cur; - - if (!obj) - return; - - cur = obj->cur; - if (!cur) { - pr_err("no pcie dma table\n"); - return; - } - - obj->dma_free = true; - obj->irq_num++; - - if (cur->dir == DMA_TO_BUS) { - if (list_empty(&obj->tbl_list)) { - if (obj->dma_free && - obj->loop_count >= obj->loop_count_threshold) - complete(&obj->done); - } - } -} - static irqreturn_t rk_pcie_sys_irq_handler(int irq, void *arg) { struct rk_pcie *rk_pcie = arg; - u32 chn = 0; + u32 chn; union int_status status; union int_clear clears; u32 reg, val; status.asdword = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS); + for (chn = 0; chn < PCIE_DMA_CHANEL_MAX_NUM; chn++) { + if (status.donesta & BIT(chn)) { + clears.doneclr = 0x1 << chn; + dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + + PCIE_DMA_WR_INT_CLEAR, clears.asdword); + if (rk_pcie->dma_obj && rk_pcie->dma_obj->cb) + rk_pcie->dma_obj->cb(rk_pcie->dma_obj, chn, DMA_TO_BUS); + } - if (rk_pcie->dma_obj && rk_pcie->dma_obj->cur) - chn = rk_pcie->dma_obj->cur->chn; - - if (status.donesta & BIT(chn)) { - clears.doneclr = 0x1 << chn; - dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + - PCIE_DMA_WR_INT_CLEAR, clears.asdword); - rk_pcie_handle_dma_interrupt(rk_pcie); - } - - if (status.abortsta & BIT(chn)) { - dev_err(rk_pcie->pci->dev, "%s, abort\n", __func__); - clears.abortclr = 0x1 << chn; - dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + - PCIE_DMA_WR_INT_CLEAR, clears.asdword); + if (status.abortsta & BIT(chn)) { + dev_err(rk_pcie->pci->dev, "%s, abort\n", __func__); + clears.abortclr = 0x1 << chn; + dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + + PCIE_DMA_WR_INT_CLEAR, clears.asdword); + } } status.asdword = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS); + for (chn = 0; chn < PCIE_DMA_CHANEL_MAX_NUM; chn++) { + if (status.donesta & BIT(chn)) { + clears.doneclr = 0x1 << chn; + dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + + PCIE_DMA_RD_INT_CLEAR, clears.asdword); + if (rk_pcie->dma_obj && rk_pcie->dma_obj->cb) + rk_pcie->dma_obj->cb(rk_pcie->dma_obj, chn, DMA_FROM_BUS); + } - if (status.donesta & BIT(chn)) { - clears.doneclr = 0x1 << chn; - dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + - PCIE_DMA_RD_INT_CLEAR, clears.asdword); - rk_pcie_handle_dma_interrupt(rk_pcie); - } - - if (status.abortsta & BIT(chn)) { - dev_err(rk_pcie->pci->dev, "%s, abort\n", __func__); - clears.abortclr = 0x1 << chn; - dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + - PCIE_DMA_RD_INT_CLEAR, clears.asdword); + if (status.abortsta & BIT(chn)) { + dev_err(rk_pcie->pci->dev, "%s, abort\n", __func__); + clears.abortclr = 0x1 << chn; + dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + + PCIE_DMA_RD_INT_CLEAR, clears.asdword); + } } reg = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC); diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c index 8d273c1c7c13..c6fcbcbc7291 100644 --- a/drivers/pci/controller/pcie-rockchip-host.c +++ b/drivers/pci/controller/pcie-rockchip-host.c @@ -40,10 +40,10 @@ #include "pcie-rockchip.h" #include "rockchip-pcie-dma.h" -static void rk_pcie_start_dma_rk3399(struct dma_trx_obj *obj) +static void rk_pcie_start_dma_rk3399(struct dma_trx_obj *obj, struct dma_table *cur) { struct rockchip_pcie *rockchip = dev_get_drvdata(obj->dev); - struct dma_table *tbl = obj->cur; + struct dma_table *tbl = cur; int chn = tbl->chn; rockchip_pcie_write(rockchip, (u32)(tbl->phys_descs & 0xffffffff), diff --git a/drivers/pci/controller/rockchip-pcie-dma.c b/drivers/pci/controller/rockchip-pcie-dma.c index 458f012c2ddd..6ffd33514095 100644 --- a/drivers/pci/controller/rockchip-pcie-dma.c +++ b/drivers/pci/controller/rockchip-pcie-dma.c @@ -154,6 +154,30 @@ static unsigned int rk_pcie_check_sum(unsigned int *src, int size) return result; } +static int rk_pcie_handle_dma_interrupt(struct dma_trx_obj *obj, u32 chn, enum dma_dir dir) +{ + struct dma_table *cur; + + cur = obj->cur; + if (!cur) { + pr_err("no pcie dma table\n"); + return 0; + } + + obj->dma_free = true; + obj->irq_num++; + + if (cur->dir == DMA_TO_BUS) { + if (list_empty(&obj->tbl_list)) { + if (obj->dma_free && + obj->loop_count >= obj->loop_count_threshold) + complete(&obj->done); + } + } + + return 0; +} + static void rk_pcie_prepare_dma(struct dma_trx_obj *obj, unsigned int idx, unsigned int bus_idx, unsigned int local_idx, size_t buf_size, @@ -295,7 +319,7 @@ static void rk_pcie_dma_trx_work(struct work_struct *work) return; } reinit_completion(&obj->done); - obj->start_dma_func(obj); + obj->start_dma_func(obj, table); } } } @@ -483,7 +507,7 @@ static void rk_pcie_send_addr_to_remote(struct dma_trx_obj *obj) table->chn = PCIE_DMA_DEFAULT_CHN; obj->config_dma_func(table); obj->cur = table; - obj->start_dma_func(obj); + obj->start_dma_func(obj, table); } static long rk_pcie_misc_ioctl(struct file *filp, unsigned int cmd, @@ -940,8 +964,9 @@ struct dma_trx_obj *rk_pcie_dma_obj_probe(struct device *dev) obj->irq_num = 0; obj->loop_count_threshold = 0; obj->ref_count = 0; - obj->version = 0x3; + obj->version = 0x4; init_completion(&obj->done); + obj->cb = rk_pcie_handle_dma_interrupt; mutex_init(&obj->count_mutex); rk_pcie_add_misc(obj); diff --git a/drivers/pci/controller/rockchip-pcie-dma.h b/drivers/pci/controller/rockchip-pcie-dma.h index 01f41947dac4..8ac55f021025 100644 --- a/drivers/pci/controller/rockchip-pcie-dma.h +++ b/drivers/pci/controller/rockchip-pcie-dma.h @@ -188,8 +188,9 @@ struct dma_trx_obj { unsigned long irq_num; struct dentry *pcie_root; struct pcie_misc_dev *pcie_dev; - void (*start_dma_func)(struct dma_trx_obj *obj); + void (*start_dma_func)(struct dma_trx_obj *obj, struct dma_table *table); void (*config_dma_func)(struct dma_table *table); + int (*cb)(struct dma_trx_obj *obj, u32 chn, enum dma_dir dir); ktime_t begin; ktime_t end; u64 cache_time_total;