Re: [PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support

2016-09-06 Thread Nicolin Chen
On Tue, Sep 06, 2016 at 12:52:03PM +0100, Jon Hunter wrote:
> > +   /* TODO: ADMA should support up to 8 chunks or periods */
> > +   desc->num_periods = 1;
> > +   desc->buf_len = buf_len;
> > +   desc->period_len = buf_len;

> What would be the benefit of using 8 periods here? My understanding is
> that you will get an interrupt per period and do you really want this
> for memcpy?

You are right about the interrupt. And it doesn't seem to be
beneficial unless the period size is over the limitation of
Transfer Count, which is rare but might theoretically exist?

I admit the "TODO" word here is a bit misleading for memcpy.
I can remove the word and write a more appropriate comments.


Re: [PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support

2016-09-06 Thread Nicolin Chen
On Tue, Sep 06, 2016 at 12:52:03PM +0100, Jon Hunter wrote:
> > +   /* TODO: ADMA should support up to 8 chunks or periods */
> > +   desc->num_periods = 1;
> > +   desc->buf_len = buf_len;
> > +   desc->period_len = buf_len;

> What would be the benefit of using 8 periods here? My understanding is
> that you will get an interrupt per period and do you really want this
> for memcpy?

You are right about the interrupt. And it doesn't seem to be
beneficial unless the period size is over the limitation of
Transfer Count, which is rare but might theoretically exist?

I admit the "TODO" word here is a bit misleading for memcpy.
I can remove the word and write a more appropriate comments.


Re: [PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support

2016-09-06 Thread Jon Hunter

On 03/09/16 01:32, Nicolin Chen wrote:
> ADMA supports non-flow controlled Memory-to-Memory direction
> transactions. So this patch just adds an initial support for
> that. It passed a simple dmatest:
> echo dma1chan0 > /sys/module/dmatest/parameters/channel
>   echo 1024 > /sys/module/dmatest/parameters/iterations
>   echo 0 > /sys/module/dmatest/parameters/dmatest
>   echo 1 > /sys/module/dmatest/parameters/run
>   dmesg | grep dmatest
> Started 1 threads using dma1chan0
> dma1chan0-copy0: summary 1024 tests, 0 failures 2054 iops 16520 KB/s (0)
> 
> Signed-off-by: Nicolin Chen 
> ---
>  drivers/dma/tegra210-adma.c | 95 
> +++--
>  1 file changed, 83 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
> index 5b5d298..d62b373 100644
> --- a/drivers/dma/tegra210-adma.c
> +++ b/drivers/dma/tegra210-adma.c
> @@ -42,9 +42,14 @@
>  #define ADMA_CH_CTRL_RX_REQ(val) (((val) & 0xf) << 24)
>  #define ADMA_CH_CTRL_RX_REQ_MAX  10
>  #define ADMA_CH_CTRL_DIR(val)(((val) & 0xf) 
> << 12)
> +#define ADMA_CH_CTRL_DIR_MEM2MEM 1
>  #define ADMA_CH_CTRL_DIR_AHUB2MEM2
>  #define ADMA_CH_CTRL_DIR_MEM2AHUB4
> -#define ADMA_CH_CTRL_MODE_CONTINUOUS (2 << 8)
> +#define ADMA_CH_CTRL_DIR_AHUB2AHUB   8
> +#define ADMA_CH_CTRL_MODE(val)   (((val) & 0x7) 
> << 8)
> +#define ADMA_CH_CTRL_MODE_ONCE   1
> +#define ADMA_CH_CTRL_MODE_CONTINUOUS 2
> +#define ADMA_CH_CTRL_MODE_LINKED_LIST4
>  #define ADMA_CH_CTRL_FLOWCTRL_EN BIT(1)
>  
>  #define ADMA_CH_CONFIG   0x28
> @@ -264,6 +269,9 @@ static int tegra_adma_request_alloc(struct 
> tegra_adma_chan *tdc,
>   }
>   break;
>  
> + case DMA_MEM_TO_MEM:
> + break;
> +
>   default:
>   dev_WARN(tdma->dev, "channel %s has invalid transfer type\n",
>dma_chan_name(>vc.chan));
> @@ -292,6 +300,9 @@ static void tegra_adma_request_free(struct 
> tegra_adma_chan *tdc)
>   clear_bit(tdc->sreq_index, >rx_requests_reserved);
>   break;
>  
> + case DMA_MEM_TO_MEM:
> + break;
> +
>   default:
>   dev_WARN(tdma->dev, "channel %s has invalid transfer type\n",
>dma_chan_name(>vc.chan));
> @@ -409,8 +420,14 @@ static irqreturn_t tegra_adma_isr(int irq, void *dev_id)
>   return IRQ_NONE;
>   }
>  
> - if (tdc->desc->cyclic)
> + if (tdc->desc->cyclic) {
>   vchan_cyclic_callback(>desc->vd);
> + } else {
> + /* Disable the channel */
> + tdma_ch_write(tdc, ADMA_CH_CMD, 0);
> + vchan_cookie_complete(>desc->vd);
> + tdc->desc = NULL;
> + }
>  
>   spin_unlock_irqrestore(>vc.lock, flags);
>  
> @@ -488,42 +505,59 @@ static enum dma_status tegra_adma_tx_status(struct 
> dma_chan *dc,
>  static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
> struct tegra_adma_desc *desc,
> dma_addr_t buf_addr,
> +   dma_addr_t buf_addr2,
> enum dma_transfer_direction direction)
>  {
>   struct tegra_adma_chan_regs *ch_regs = >ch_regs;
> - unsigned int burst_size, adma_dir;
> + unsigned int num_periods = desc->num_periods;
> + unsigned int burst_size, adma_dir, adma_mode;
>  
> - if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS)
> + if (num_periods > ADMA_CH_CONFIG_MAX_BUFS)
>   return -EINVAL;
>  
>   switch (direction) {
>   case DMA_MEM_TO_DEV:
>   adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB;
>   burst_size = fls(tdc->sconfig.dst_maxburst);
> - ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1);
> - ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index);
> + ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(num_periods - 1);
> + ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index) |
> + ADMA_CH_CTRL_FLOWCTRL_EN;
>   ch_regs->src_addr = buf_addr;
>   break;
>  
>   case DMA_DEV_TO_MEM:
>   adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM;
>   burst_size = fls(tdc->sconfig.src_maxburst);
> - ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1);
> - ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index);
> + ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(num_periods - 1);
> + ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index) |
> +   

Re: [PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support

2016-09-06 Thread Jon Hunter

On 03/09/16 01:32, Nicolin Chen wrote:
> ADMA supports non-flow controlled Memory-to-Memory direction
> transactions. So this patch just adds an initial support for
> that. It passed a simple dmatest:
> echo dma1chan0 > /sys/module/dmatest/parameters/channel
>   echo 1024 > /sys/module/dmatest/parameters/iterations
>   echo 0 > /sys/module/dmatest/parameters/dmatest
>   echo 1 > /sys/module/dmatest/parameters/run
>   dmesg | grep dmatest
> Started 1 threads using dma1chan0
> dma1chan0-copy0: summary 1024 tests, 0 failures 2054 iops 16520 KB/s (0)
> 
> Signed-off-by: Nicolin Chen 
> ---
>  drivers/dma/tegra210-adma.c | 95 
> +++--
>  1 file changed, 83 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
> index 5b5d298..d62b373 100644
> --- a/drivers/dma/tegra210-adma.c
> +++ b/drivers/dma/tegra210-adma.c
> @@ -42,9 +42,14 @@
>  #define ADMA_CH_CTRL_RX_REQ(val) (((val) & 0xf) << 24)
>  #define ADMA_CH_CTRL_RX_REQ_MAX  10
>  #define ADMA_CH_CTRL_DIR(val)(((val) & 0xf) 
> << 12)
> +#define ADMA_CH_CTRL_DIR_MEM2MEM 1
>  #define ADMA_CH_CTRL_DIR_AHUB2MEM2
>  #define ADMA_CH_CTRL_DIR_MEM2AHUB4
> -#define ADMA_CH_CTRL_MODE_CONTINUOUS (2 << 8)
> +#define ADMA_CH_CTRL_DIR_AHUB2AHUB   8
> +#define ADMA_CH_CTRL_MODE(val)   (((val) & 0x7) 
> << 8)
> +#define ADMA_CH_CTRL_MODE_ONCE   1
> +#define ADMA_CH_CTRL_MODE_CONTINUOUS 2
> +#define ADMA_CH_CTRL_MODE_LINKED_LIST4
>  #define ADMA_CH_CTRL_FLOWCTRL_EN BIT(1)
>  
>  #define ADMA_CH_CONFIG   0x28
> @@ -264,6 +269,9 @@ static int tegra_adma_request_alloc(struct 
> tegra_adma_chan *tdc,
>   }
>   break;
>  
> + case DMA_MEM_TO_MEM:
> + break;
> +
>   default:
>   dev_WARN(tdma->dev, "channel %s has invalid transfer type\n",
>dma_chan_name(>vc.chan));
> @@ -292,6 +300,9 @@ static void tegra_adma_request_free(struct 
> tegra_adma_chan *tdc)
>   clear_bit(tdc->sreq_index, >rx_requests_reserved);
>   break;
>  
> + case DMA_MEM_TO_MEM:
> + break;
> +
>   default:
>   dev_WARN(tdma->dev, "channel %s has invalid transfer type\n",
>dma_chan_name(>vc.chan));
> @@ -409,8 +420,14 @@ static irqreturn_t tegra_adma_isr(int irq, void *dev_id)
>   return IRQ_NONE;
>   }
>  
> - if (tdc->desc->cyclic)
> + if (tdc->desc->cyclic) {
>   vchan_cyclic_callback(>desc->vd);
> + } else {
> + /* Disable the channel */
> + tdma_ch_write(tdc, ADMA_CH_CMD, 0);
> + vchan_cookie_complete(>desc->vd);
> + tdc->desc = NULL;
> + }
>  
>   spin_unlock_irqrestore(>vc.lock, flags);
>  
> @@ -488,42 +505,59 @@ static enum dma_status tegra_adma_tx_status(struct 
> dma_chan *dc,
>  static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
> struct tegra_adma_desc *desc,
> dma_addr_t buf_addr,
> +   dma_addr_t buf_addr2,
> enum dma_transfer_direction direction)
>  {
>   struct tegra_adma_chan_regs *ch_regs = >ch_regs;
> - unsigned int burst_size, adma_dir;
> + unsigned int num_periods = desc->num_periods;
> + unsigned int burst_size, adma_dir, adma_mode;
>  
> - if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS)
> + if (num_periods > ADMA_CH_CONFIG_MAX_BUFS)
>   return -EINVAL;
>  
>   switch (direction) {
>   case DMA_MEM_TO_DEV:
>   adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB;
>   burst_size = fls(tdc->sconfig.dst_maxburst);
> - ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1);
> - ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index);
> + ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(num_periods - 1);
> + ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index) |
> + ADMA_CH_CTRL_FLOWCTRL_EN;
>   ch_regs->src_addr = buf_addr;
>   break;
>  
>   case DMA_DEV_TO_MEM:
>   adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM;
>   burst_size = fls(tdc->sconfig.src_maxburst);
> - ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1);
> - ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index);
> + ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(num_periods - 1);
> + ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index) |
> + 

[PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support

2016-09-02 Thread Nicolin Chen
ADMA supports non-flow controlled Memory-to-Memory direction
transactions. So this patch just adds an initial support for
that. It passed a simple dmatest:
echo dma1chan0 > /sys/module/dmatest/parameters/channel
echo 1024 > /sys/module/dmatest/parameters/iterations
echo 0 > /sys/module/dmatest/parameters/dmatest
echo 1 > /sys/module/dmatest/parameters/run
dmesg | grep dmatest
Started 1 threads using dma1chan0
dma1chan0-copy0: summary 1024 tests, 0 failures 2054 iops 16520 KB/s (0)

Signed-off-by: Nicolin Chen 
---
 drivers/dma/tegra210-adma.c | 95 +++--
 1 file changed, 83 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index 5b5d298..d62b373 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -42,9 +42,14 @@
 #define ADMA_CH_CTRL_RX_REQ(val)   (((val) & 0xf) << 24)
 #define ADMA_CH_CTRL_RX_REQ_MAX10
 #define ADMA_CH_CTRL_DIR(val)  (((val) & 0xf) << 12)
+#define ADMA_CH_CTRL_DIR_MEM2MEM   1
 #define ADMA_CH_CTRL_DIR_AHUB2MEM  2
 #define ADMA_CH_CTRL_DIR_MEM2AHUB  4
-#define ADMA_CH_CTRL_MODE_CONTINUOUS   (2 << 8)
+#define ADMA_CH_CTRL_DIR_AHUB2AHUB 8
+#define ADMA_CH_CTRL_MODE(val) (((val) & 0x7) << 8)
+#define ADMA_CH_CTRL_MODE_ONCE 1
+#define ADMA_CH_CTRL_MODE_CONTINUOUS   2
+#define ADMA_CH_CTRL_MODE_LINKED_LIST  4
 #define ADMA_CH_CTRL_FLOWCTRL_EN   BIT(1)
 
 #define ADMA_CH_CONFIG 0x28
@@ -264,6 +269,9 @@ static int tegra_adma_request_alloc(struct tegra_adma_chan 
*tdc,
}
break;
 
+   case DMA_MEM_TO_MEM:
+   break;
+
default:
dev_WARN(tdma->dev, "channel %s has invalid transfer type\n",
 dma_chan_name(>vc.chan));
@@ -292,6 +300,9 @@ static void tegra_adma_request_free(struct tegra_adma_chan 
*tdc)
clear_bit(tdc->sreq_index, >rx_requests_reserved);
break;
 
+   case DMA_MEM_TO_MEM:
+   break;
+
default:
dev_WARN(tdma->dev, "channel %s has invalid transfer type\n",
 dma_chan_name(>vc.chan));
@@ -409,8 +420,14 @@ static irqreturn_t tegra_adma_isr(int irq, void *dev_id)
return IRQ_NONE;
}
 
-   if (tdc->desc->cyclic)
+   if (tdc->desc->cyclic) {
vchan_cyclic_callback(>desc->vd);
+   } else {
+   /* Disable the channel */
+   tdma_ch_write(tdc, ADMA_CH_CMD, 0);
+   vchan_cookie_complete(>desc->vd);
+   tdc->desc = NULL;
+   }
 
spin_unlock_irqrestore(>vc.lock, flags);
 
@@ -488,42 +505,59 @@ static enum dma_status tegra_adma_tx_status(struct 
dma_chan *dc,
 static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
  struct tegra_adma_desc *desc,
  dma_addr_t buf_addr,
+ dma_addr_t buf_addr2,
  enum dma_transfer_direction direction)
 {
struct tegra_adma_chan_regs *ch_regs = >ch_regs;
-   unsigned int burst_size, adma_dir;
+   unsigned int num_periods = desc->num_periods;
+   unsigned int burst_size, adma_dir, adma_mode;
 
-   if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS)
+   if (num_periods > ADMA_CH_CONFIG_MAX_BUFS)
return -EINVAL;
 
switch (direction) {
case DMA_MEM_TO_DEV:
adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB;
burst_size = fls(tdc->sconfig.dst_maxburst);
-   ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1);
-   ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index);
+   ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(num_periods - 1);
+   ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index) |
+   ADMA_CH_CTRL_FLOWCTRL_EN;
ch_regs->src_addr = buf_addr;
break;
 
case DMA_DEV_TO_MEM:
adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM;
burst_size = fls(tdc->sconfig.src_maxburst);
-   ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1);
-   ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index);
+   ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(num_periods - 1);
+   ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index) |
+   ADMA_CH_CTRL_FLOWCTRL_EN;
ch_regs->trg_addr = buf_addr;
break;
 
+   case DMA_MEM_TO_MEM:
+   

[PATCH v2 2/2] dmaengine: tegra210-adma: Add memcpy support

2016-09-02 Thread Nicolin Chen
ADMA supports non-flow controlled Memory-to-Memory direction
transactions. So this patch just adds an initial support for
that. It passed a simple dmatest:
echo dma1chan0 > /sys/module/dmatest/parameters/channel
echo 1024 > /sys/module/dmatest/parameters/iterations
echo 0 > /sys/module/dmatest/parameters/dmatest
echo 1 > /sys/module/dmatest/parameters/run
dmesg | grep dmatest
Started 1 threads using dma1chan0
dma1chan0-copy0: summary 1024 tests, 0 failures 2054 iops 16520 KB/s (0)

Signed-off-by: Nicolin Chen 
---
 drivers/dma/tegra210-adma.c | 95 +++--
 1 file changed, 83 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index 5b5d298..d62b373 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -42,9 +42,14 @@
 #define ADMA_CH_CTRL_RX_REQ(val)   (((val) & 0xf) << 24)
 #define ADMA_CH_CTRL_RX_REQ_MAX10
 #define ADMA_CH_CTRL_DIR(val)  (((val) & 0xf) << 12)
+#define ADMA_CH_CTRL_DIR_MEM2MEM   1
 #define ADMA_CH_CTRL_DIR_AHUB2MEM  2
 #define ADMA_CH_CTRL_DIR_MEM2AHUB  4
-#define ADMA_CH_CTRL_MODE_CONTINUOUS   (2 << 8)
+#define ADMA_CH_CTRL_DIR_AHUB2AHUB 8
+#define ADMA_CH_CTRL_MODE(val) (((val) & 0x7) << 8)
+#define ADMA_CH_CTRL_MODE_ONCE 1
+#define ADMA_CH_CTRL_MODE_CONTINUOUS   2
+#define ADMA_CH_CTRL_MODE_LINKED_LIST  4
 #define ADMA_CH_CTRL_FLOWCTRL_EN   BIT(1)
 
 #define ADMA_CH_CONFIG 0x28
@@ -264,6 +269,9 @@ static int tegra_adma_request_alloc(struct tegra_adma_chan 
*tdc,
}
break;
 
+   case DMA_MEM_TO_MEM:
+   break;
+
default:
dev_WARN(tdma->dev, "channel %s has invalid transfer type\n",
 dma_chan_name(>vc.chan));
@@ -292,6 +300,9 @@ static void tegra_adma_request_free(struct tegra_adma_chan 
*tdc)
clear_bit(tdc->sreq_index, >rx_requests_reserved);
break;
 
+   case DMA_MEM_TO_MEM:
+   break;
+
default:
dev_WARN(tdma->dev, "channel %s has invalid transfer type\n",
 dma_chan_name(>vc.chan));
@@ -409,8 +420,14 @@ static irqreturn_t tegra_adma_isr(int irq, void *dev_id)
return IRQ_NONE;
}
 
-   if (tdc->desc->cyclic)
+   if (tdc->desc->cyclic) {
vchan_cyclic_callback(>desc->vd);
+   } else {
+   /* Disable the channel */
+   tdma_ch_write(tdc, ADMA_CH_CMD, 0);
+   vchan_cookie_complete(>desc->vd);
+   tdc->desc = NULL;
+   }
 
spin_unlock_irqrestore(>vc.lock, flags);
 
@@ -488,42 +505,59 @@ static enum dma_status tegra_adma_tx_status(struct 
dma_chan *dc,
 static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
  struct tegra_adma_desc *desc,
  dma_addr_t buf_addr,
+ dma_addr_t buf_addr2,
  enum dma_transfer_direction direction)
 {
struct tegra_adma_chan_regs *ch_regs = >ch_regs;
-   unsigned int burst_size, adma_dir;
+   unsigned int num_periods = desc->num_periods;
+   unsigned int burst_size, adma_dir, adma_mode;
 
-   if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS)
+   if (num_periods > ADMA_CH_CONFIG_MAX_BUFS)
return -EINVAL;
 
switch (direction) {
case DMA_MEM_TO_DEV:
adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB;
burst_size = fls(tdc->sconfig.dst_maxburst);
-   ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1);
-   ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index);
+   ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(num_periods - 1);
+   ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index) |
+   ADMA_CH_CTRL_FLOWCTRL_EN;
ch_regs->src_addr = buf_addr;
break;
 
case DMA_DEV_TO_MEM:
adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM;
burst_size = fls(tdc->sconfig.src_maxburst);
-   ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1);
-   ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index);
+   ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(num_periods - 1);
+   ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index) |
+   ADMA_CH_CTRL_FLOWCTRL_EN;
ch_regs->trg_addr = buf_addr;
break;
 
+   case DMA_MEM_TO_MEM:
+   adma_dir =