summaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorLudovic Desroches <ludovic.desroches@atmel.com>2015-01-27 10:30:31 -0500
committerVinod Koul <vinod.koul@intel.com>2015-02-05 02:12:29 -0500
commitbe835074829b13c5f635ef78ed911b13b9c15fa9 (patch)
tree2cdb8e53d78deeb46bc132b191015ad9d39b8f13 /drivers/dma
parent734bb9a7b3e198ba3b7d12565dce31d1568ab018 (diff)
dmaengine: at_xdmac: simplify channel configuration stuff
This patch simplifies the channel configuration register management. Relying on a "software snapshot" of the configuration is not safe and too complex. Multiple dwidths will be introduced for slave transfers. In this case, it becomes quite difficult to have an accurate snapshot of the channel configuration register in the way it is done. Using the channel configuration available in the lli descriptor simplifies this stuff. Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/at_xdmac.c36
1 files changed, 14 insertions, 22 deletions
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 8aebf1833284..eba66a22a265 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -191,10 +191,9 @@ struct at_xdmac_chan {
191 struct dma_chan chan; 191 struct dma_chan chan;
192 void __iomem *ch_regs; 192 void __iomem *ch_regs;
193 u32 mask; /* Channel Mask */ 193 u32 mask; /* Channel Mask */
194 u32 cfg[3]; /* Channel Configuration Register */ 194 u32 cfg[2]; /* Channel Configuration Register */
195 #define AT_XDMAC_CUR_CFG 0 /* Current channel conf */ 195 #define AT_XDMAC_DEV_TO_MEM_CFG 0 /* Predifined dev to mem channel conf */
196 #define AT_XDMAC_DEV_TO_MEM_CFG 1 /* Predifined dev to mem channel conf */ 196 #define AT_XDMAC_MEM_TO_DEV_CFG 1 /* Predifined mem to dev channel conf */
197 #define AT_XDMAC_MEM_TO_DEV_CFG 2 /* Predifined mem to dev channel conf */
198 u8 perid; /* Peripheral ID */ 197 u8 perid; /* Peripheral ID */
199 u8 perif; /* Peripheral Interface */ 198 u8 perif; /* Peripheral Interface */
200 u8 memif; /* Memory Interface */ 199 u8 memif; /* Memory Interface */
@@ -358,14 +357,7 @@ static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan,
358 */ 357 */
359 if (is_slave_direction(first->direction)) { 358 if (is_slave_direction(first->direction)) {
360 reg = AT_XDMAC_CNDC_NDVIEW_NDV1; 359 reg = AT_XDMAC_CNDC_NDVIEW_NDV1;
361 if (first->direction == DMA_MEM_TO_DEV) 360 at_xdmac_chan_write(atchan, AT_XDMAC_CC, first->lld.mbr_cfg);
362 atchan->cfg[AT_XDMAC_CUR_CFG] =
363 atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG];
364 else
365 atchan->cfg[AT_XDMAC_CUR_CFG] =
366 atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG];
367 at_xdmac_chan_write(atchan, AT_XDMAC_CC,
368 atchan->cfg[AT_XDMAC_CUR_CFG]);
369 } else { 361 } else {
370 /* 362 /*
371 * No need to write AT_XDMAC_CC reg, it will be done when the 363 * No need to write AT_XDMAC_CC reg, it will be done when the
@@ -569,7 +561,6 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
569 struct at_xdmac_desc *first = NULL, *prev = NULL; 561 struct at_xdmac_desc *first = NULL, *prev = NULL;
570 struct scatterlist *sg; 562 struct scatterlist *sg;
571 int i; 563 int i;
572 u32 cfg;
573 unsigned int xfer_size = 0; 564 unsigned int xfer_size = 0;
574 565
575 if (!sgl) 566 if (!sgl)
@@ -616,17 +607,17 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
616 if (direction == DMA_DEV_TO_MEM) { 607 if (direction == DMA_DEV_TO_MEM) {
617 desc->lld.mbr_sa = atchan->per_src_addr; 608 desc->lld.mbr_sa = atchan->per_src_addr;
618 desc->lld.mbr_da = mem; 609 desc->lld.mbr_da = mem;
619 cfg = atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG]; 610 desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG];
620 } else { 611 } else {
621 desc->lld.mbr_sa = mem; 612 desc->lld.mbr_sa = mem;
622 desc->lld.mbr_da = atchan->per_dst_addr; 613 desc->lld.mbr_da = atchan->per_dst_addr;
623 cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG]; 614 desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG];
624 } 615 }
625 desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV1 /* next descriptor view */ 616 desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV1 /* next descriptor view */
626 | AT_XDMAC_MBR_UBC_NDEN /* next descriptor dst parameter update */ 617 | AT_XDMAC_MBR_UBC_NDEN /* next descriptor dst parameter update */
627 | AT_XDMAC_MBR_UBC_NSEN /* next descriptor src parameter update */ 618 | AT_XDMAC_MBR_UBC_NSEN /* next descriptor src parameter update */
628 | (i == sg_len - 1 ? 0 : AT_XDMAC_MBR_UBC_NDE) /* descriptor fetch */ 619 | (i == sg_len - 1 ? 0 : AT_XDMAC_MBR_UBC_NDE) /* descriptor fetch */
629 | len / (1 << at_xdmac_get_dwidth(cfg)); /* microblock length */ 620 | len / (1 << at_xdmac_get_dwidth(desc->lld.mbr_cfg)); /* microblock length */
630 dev_dbg(chan2dev(chan), 621 dev_dbg(chan2dev(chan),
631 "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n", 622 "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n",
632 __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc); 623 __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc);
@@ -890,7 +881,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
890 enum dma_status ret; 881 enum dma_status ret;
891 int residue; 882 int residue;
892 u32 cur_nda, mask, value; 883 u32 cur_nda, mask, value;
893 u8 dwidth = at_xdmac_get_dwidth(atchan->cfg[AT_XDMAC_CUR_CFG]); 884 u8 dwidth = 0;
894 885
895 ret = dma_cookie_status(chan, cookie, txstate); 886 ret = dma_cookie_status(chan, cookie, txstate);
896 if (ret == DMA_COMPLETE) 887 if (ret == DMA_COMPLETE)
@@ -920,7 +911,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
920 */ 911 */
921 mask = AT_XDMAC_CC_TYPE | AT_XDMAC_CC_DSYNC; 912 mask = AT_XDMAC_CC_TYPE | AT_XDMAC_CC_DSYNC;
922 value = AT_XDMAC_CC_TYPE_PER_TRAN | AT_XDMAC_CC_DSYNC_PER2MEM; 913 value = AT_XDMAC_CC_TYPE_PER_TRAN | AT_XDMAC_CC_DSYNC_PER2MEM;
923 if ((atchan->cfg[AT_XDMAC_CUR_CFG] & mask) == value) { 914 if ((desc->lld.mbr_cfg & mask) == value) {
924 at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask); 915 at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask);
925 while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS)) 916 while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS))
926 cpu_relax(); 917 cpu_relax();
@@ -934,6 +925,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
934 */ 925 */
935 descs_list = &desc->descs_list; 926 descs_list = &desc->descs_list;
936 list_for_each_entry_safe(desc, _desc, descs_list, desc_node) { 927 list_for_each_entry_safe(desc, _desc, descs_list, desc_node) {
928 dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg);
937 residue -= (desc->lld.mbr_ubc & 0xffffff) << dwidth; 929 residue -= (desc->lld.mbr_ubc & 0xffffff) << dwidth;
938 if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda) 930 if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda)
939 break; 931 break;