diff options
author | Tero Kristo <t-kristo@ti.com> | 2017-12-29 11:47:46 +0530 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2018-01-19 15:49:25 -0500 |
commit | 72b7af5a04afc22913e943decc1733a25b8eefcf (patch) | |
tree | 94fa937f7d9e32ec0f223810a9ed64ee7a43d83a /drivers/dma | |
parent | 445277b9d1efcc239c8c05560e4db312ea4f078e (diff) |
drivers: dma: ti-edma3: add support for memory fill
Add support for simple memory fill operation. With large data sizes
it is much faster to use EDMA for memory fill rather than CPU.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/ti-edma3.c | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/drivers/dma/ti-edma3.c b/drivers/dma/ti-edma3.c index 635eb7876d5..852c9e1fd7f 100644 --- a/drivers/dma/ti-edma3.c +++ b/drivers/dma/ti-edma3.c @@ -34,10 +34,14 @@ #define EDMA3_QEESR 0x108c #define EDMA3_QSECR 0x1094 +#define EDMA_FILL_BUFFER_SIZE 512 + struct ti_edma3_priv { u32 base; }; +static u8 edma_fill_buffer[EDMA_FILL_BUFFER_SIZE] __aligned(ARCH_DMA_MINALIGN); + /** * qedma3_start - start qdma on a channel * @base: base address of edma @@ -391,7 +395,7 @@ void qedma3_stop(u32 base, struct edma3_channel_config *cfg) } void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num, - void *dst, void *src, size_t len) + void *dst, void *src, size_t len, size_t s_len) { struct edma3_slot_config slot; struct edma3_channel_config edma_channel; @@ -401,7 +405,11 @@ void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num, unsigned int addr = (unsigned int) (dst); unsigned int max_acnt = 0x7FFFU; - if (len > max_acnt) { + if (len > s_len) { + b_cnt_value = (len / s_len); + rem_bytes = (len % s_len); + a_cnt_value = s_len; + } else if (len > max_acnt) { b_cnt_value = (len / max_acnt); rem_bytes = (len % max_acnt); a_cnt_value = max_acnt; @@ -412,7 +420,10 @@ void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num, slot.acnt = a_cnt_value; slot.bcnt = b_cnt_value; slot.ccnt = 1; - slot.src_bidx = a_cnt_value; + if (len == s_len) + slot.src_bidx = a_cnt_value; + else + slot.src_bidx = 0; slot.dst_bidx = a_cnt_value; slot.src_cidx = 0; slot.dst_cidx = 0; @@ -438,8 +449,11 @@ void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num, if (rem_bytes != 0) { slot.opt = 0; - slot.src = - (b_cnt_value * max_acnt) + ((unsigned int) src); + if (len == s_len) + slot.src = + (b_cnt_value * max_acnt) + ((unsigned int) src); + else + slot.src = (unsigned int) src; slot.acnt = rem_bytes; slot.bcnt = 1; slot.ccnt = 1; @@ -468,12 +482,39 @@ void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num, } } +void __edma3_fill(unsigned long edma3_base_addr, unsigned int edma_slot_num, + void *dst, u8 val, size_t len) +{ + int xfer_len; + int max_xfer = EDMA_FILL_BUFFER_SIZE * 65535; + + memset((void *)edma_fill_buffer, val, sizeof(edma_fill_buffer)); + + while (len) { + xfer_len = len; + if (xfer_len > max_xfer) + xfer_len = max_xfer; + + __edma3_transfer(edma3_base_addr, edma_slot_num, dst, + edma_fill_buffer, xfer_len, + EDMA_FILL_BUFFER_SIZE); + len -= xfer_len; + dst += xfer_len; + } +} + #ifndef CONFIG_DMA void edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num, void *dst, void *src, size_t len) { - __edma3_transfer(edma3_base_addr, edma_slot_num, dst, src, len); + __edma3_transfer(edma3_base_addr, edma_slot_num, dst, src, len, len); +} + +void edma3_fill(unsigned long edma3_base_addr, unsigned int edma_slot_num, + void *dst, u8 val, size_t len) +{ + __edma3_fill(edma3_base_addr, edma_slot_num, dst, val, len); } #else @@ -488,7 +529,7 @@ static int ti_edma3_transfer(struct udevice *dev, int direction, void *dst, switch (direction) { case DMA_MEM_TO_MEM: - __edma3_transfer(priv->base, 1, dst, src, len); + __edma3_transfer(priv->base, 1, dst, src, len, len); break; default: pr_err("Transfer type not implemented in DMA driver\n"); |