aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/at_xdmac.c
diff options
context:
space:
mode:
authorLudovic Desroches <ludovic.desroches@atmel.com>2015-01-27 10:30:32 -0500
committerVinod Koul <vinod.koul@intel.com>2015-02-05 02:12:29 -0500
commit6d3a7d9e3ada345948f72564ce638c412ccd8c4a (patch)
treed76e829bc3b094b12676cf6ff7220615412da764 /drivers/dma/at_xdmac.c
parentbe835074829b13c5f635ef78ed911b13b9c15fa9 (diff)
dmaengine: at_xdmac: allow muliple dwidths when doing slave transfers
When using FIFO, we need to support differents data width in a single transfer. For example, serial device which usually uses 1-byte data width will use 4-bytes data width when using the FIFO. If the transfer size is not aligned on 4-bytes then the end of the transfer will be performed with 1-byte data-width. For that reason, at_xdmac_prep_slave_sg() now builds linked list descriptors using view 2 instead of view 1 so each of them can update the DWIDTH field into the Channel Configuration Register. Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com> Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma/at_xdmac.c')
-rw-r--r--drivers/dma/at_xdmac.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index eba66a22a265..09e2825a547a 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -25,6 +25,7 @@
25#include <linux/dmapool.h> 25#include <linux/dmapool.h>
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/irq.h> 27#include <linux/irq.h>
28#include <linux/kernel.h>
28#include <linux/list.h> 29#include <linux/list.h>
29#include <linux/module.h> 30#include <linux/module.h>
30#include <linux/of_dma.h> 31#include <linux/of_dma.h>
@@ -351,11 +352,11 @@ static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan,
351 at_xdmac_chan_write(atchan, AT_XDMAC_CNDA, reg); 352 at_xdmac_chan_write(atchan, AT_XDMAC_CNDA, reg);
352 353
353 /* 354 /*
354 * When doing memory to memory transfer we need to use the next 355 * When doing non cyclic transfer we need to use the next
355 * descriptor view 2 since some fields of the configuration register 356 * descriptor view 2 since some fields of the configuration register
356 * depend on transfer size and src/dest addresses. 357 * depend on transfer size and src/dest addresses.
357 */ 358 */
358 if (is_slave_direction(first->direction)) { 359 if (at_xdmac_chan_is_cyclic(atchan)) {
359 reg = AT_XDMAC_CNDC_NDVIEW_NDV1; 360 reg = AT_XDMAC_CNDC_NDVIEW_NDV1;
360 at_xdmac_chan_write(atchan, AT_XDMAC_CC, first->lld.mbr_cfg); 361 at_xdmac_chan_write(atchan, AT_XDMAC_CC, first->lld.mbr_cfg);
361 } else { 362 } else {
@@ -582,7 +583,7 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
582 /* Prepare descriptors. */ 583 /* Prepare descriptors. */
583 for_each_sg(sgl, sg, sg_len, i) { 584 for_each_sg(sgl, sg, sg_len, i) {
584 struct at_xdmac_desc *desc = NULL; 585 struct at_xdmac_desc *desc = NULL;
585 u32 len, mem; 586 u32 len, mem, dwidth, fixed_dwidth;
586 587
587 len = sg_dma_len(sg); 588 len = sg_dma_len(sg);
588 mem = sg_dma_address(sg); 589 mem = sg_dma_address(sg);
@@ -613,11 +614,15 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
613 desc->lld.mbr_da = atchan->per_dst_addr; 614 desc->lld.mbr_da = atchan->per_dst_addr;
614 desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG]; 615 desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG];
615 } 616 }
616 desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV1 /* next descriptor view */ 617 dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg);
618 fixed_dwidth = IS_ALIGNED(len, 1 << dwidth)
619 ? at_xdmac_get_dwidth(desc->lld.mbr_cfg)
620 : AT_XDMAC_CC_DWIDTH_BYTE;
621 desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV2 /* next descriptor view */
617 | AT_XDMAC_MBR_UBC_NDEN /* next descriptor dst parameter update */ 622 | AT_XDMAC_MBR_UBC_NDEN /* next descriptor dst parameter update */
618 | AT_XDMAC_MBR_UBC_NSEN /* next descriptor src parameter update */ 623 | AT_XDMAC_MBR_UBC_NSEN /* next descriptor src parameter update */
619 | (i == sg_len - 1 ? 0 : AT_XDMAC_MBR_UBC_NDE) /* descriptor fetch */ 624 | (i == sg_len - 1 ? 0 : AT_XDMAC_MBR_UBC_NDE) /* descriptor fetch */
620 | len / (1 << at_xdmac_get_dwidth(desc->lld.mbr_cfg)); /* microblock length */ 625 | (len >> fixed_dwidth); /* microblock length */
621 dev_dbg(chan2dev(chan), 626 dev_dbg(chan2dev(chan),
622 "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n", 627 "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n",
623 __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc); 628 __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc);