drivers: dma: ti-edma3: add support for memory fill
authorTero Kristo <t-kristo@ti.com>
Fri, 29 Dec 2017 06:17:46 +0000 (11:47 +0530)
committerTom Rini <trini@konsulko.com>
Fri, 19 Jan 2018 20:49:25 +0000 (15:49 -0500)
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>
arch/arm/include/asm/ti-common/ti-edma3.h
drivers/dma/ti-edma3.c

index 6a7a321c1bdf1e7a90ba1bb9c4fa5ee60b2ce056..3f41d34a7a0eedd00cba20d90f6fced0902a7622 100644 (file)
@@ -119,5 +119,7 @@ void edma3_set_transfer_params(u32 base, int slot, int acnt,
                               enum edma3_sync_dimension sync_mode);
 void edma3_transfer(unsigned long edma3_base_addr, unsigned int
                edma_slot_num, void *dst, void *src, size_t len);
+void edma3_fill(unsigned long edma3_base_addr, unsigned int edma_slot_num,
+               void *dst, u8 val, size_t len);
 
 #endif
index 635eb7876d5526965a1fcf3584bdfb5dd2c3bd89..852c9e1fd7f8fb9915534077da6f353b84ff51fd 100644 (file)
 #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");