pcie-dma-trx: update to version 0x4

1.Optimize DMA hook to support multiple independent DMA channels
2.Add interrupt callback to support multiple independent DMA channels

Change-Id: I42a638a4cb9fa61ebc1cd51d4e9f6d6942715fd1
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
This commit is contained in:
Jon Lin
2022-08-23 15:04:47 +08:00
committed by Tao Huang
parent 0d01ed0d12
commit 73635093a1
4 changed files with 70 additions and 70 deletions

View File

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

View File

@@ -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),

View File

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

View File

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