diff options
author | Eric Long <eric.long@spreadtrum.com> | 2018-11-06 08:01:32 +0300 |
---|---|---|
committer | Vinod Koul <vkoul@kernel.org> | 2018-12-05 11:57:11 +0300 |
commit | d762ab33ccd03e8c1ad50b814d2deccec15b8c28 (patch) | |
tree | 16ce83a4ae2e985e3894aff9e17638b7be3ccc74 /drivers/dma/sprd-dma.c | |
parent | a0ecabf503413446f08deb8f7226b6135cf922b0 (diff) |
dmaengine: sprd: Get transfer residue depending on the transfer direction
Add one field to save the transfer direction for struct sprd_dma_desc,
which is used to get correct transfer residue depending on the transfer
direction.
[Baolin Wang adds one field to present the transfer direction]
Signed-off-by: Eric Long <eric.long@spreadtrum.com>
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Diffstat (limited to 'drivers/dma/sprd-dma.c')
-rw-r--r-- | drivers/dma/sprd-dma.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c index c226dc93e401..4f3587b826da 100644 --- a/drivers/dma/sprd-dma.c +++ b/drivers/dma/sprd-dma.c @@ -159,6 +159,7 @@ struct sprd_dma_chn_hw { struct sprd_dma_desc { struct virt_dma_desc vd; struct sprd_dma_chn_hw chn_hw; + enum dma_transfer_direction dir; }; /* dma channel description */ @@ -331,6 +332,17 @@ static void sprd_dma_stop_and_disable(struct sprd_dma_chn *schan) sprd_dma_disable_chn(schan); } +static unsigned long sprd_dma_get_src_addr(struct sprd_dma_chn *schan) +{ + unsigned long addr, addr_high; + + addr = readl(schan->chn_base + SPRD_DMA_CHN_SRC_ADDR); + addr_high = readl(schan->chn_base + SPRD_DMA_CHN_WARP_PTR) & + SPRD_DMA_HIGH_ADDR_MASK; + + return addr | (addr_high << SPRD_DMA_HIGH_ADDR_OFFSET); +} + static unsigned long sprd_dma_get_dst_addr(struct sprd_dma_chn *schan) { unsigned long addr, addr_high; @@ -534,7 +546,12 @@ static enum dma_status sprd_dma_tx_status(struct dma_chan *chan, else pos = 0; } else if (schan->cur_desc && schan->cur_desc->vd.tx.cookie == cookie) { - pos = sprd_dma_get_dst_addr(schan); + struct sprd_dma_desc *sdesc = to_sprd_dma_desc(vd); + + if (sdesc->dir == DMA_DEV_TO_MEM) + pos = sprd_dma_get_dst_addr(schan); + else + pos = sprd_dma_get_src_addr(schan); } else { pos = 0; } @@ -804,6 +821,8 @@ sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (!sdesc) return NULL; + sdesc->dir = dir; + for_each_sg(sgl, sg, sglen, i) { len = sg_dma_len(sg); |