aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/at_xdmac.c
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2015-05-07 11:38:09 -0400
committerVinod Koul <vinod.koul@intel.com>2015-05-18 01:29:34 -0400
commitf0816a36887b5b6acb387d8a554c5f5ed4069d33 (patch)
tree2b8f075e2435a93b54cd859ef5f235e968da0452 /drivers/dma/at_xdmac.c
parentee0fe35c8dcde29e7f65c34c286378750c075bf3 (diff)
dmaengine: xdmac: Add function to align width
The code has some logic to compute the burst width according to the alignment of the address we're using. Move that in a function of its own to reduce code duplication. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Acked-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.c63
1 files changed, 32 insertions, 31 deletions
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 2d039512ecb3..cbeadeeed9c0 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -749,6 +749,35 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
749 return &first->tx_dma_desc; 749 return &first->tx_dma_desc;
750} 750}
751 751
752static inline u32 at_xdmac_align_width(struct dma_chan *chan, dma_addr_t addr)
753{
754 u32 width;
755
756 /*
757 * Check address alignment to select the greater data width we
758 * can use.
759 *
760 * Some XDMAC implementations don't provide dword transfer, in
761 * this case selecting dword has the same behavior as
762 * selecting word transfers.
763 */
764 if (!(addr & 7)) {
765 width = AT_XDMAC_CC_DWIDTH_DWORD;
766 dev_dbg(chan2dev(chan), "%s: dwidth: double word\n", __func__);
767 } else if (!(addr & 3)) {
768 width = AT_XDMAC_CC_DWIDTH_WORD;
769 dev_dbg(chan2dev(chan), "%s: dwidth: word\n", __func__);
770 } else if (!(addr & 1)) {
771 width = AT_XDMAC_CC_DWIDTH_HALFWORD;
772 dev_dbg(chan2dev(chan), "%s: dwidth: half word\n", __func__);
773 } else {
774 width = AT_XDMAC_CC_DWIDTH_BYTE;
775 dev_dbg(chan2dev(chan), "%s: dwidth: byte\n", __func__);
776 }
777
778 return width;
779}
780
752static struct dma_async_tx_descriptor * 781static struct dma_async_tx_descriptor *
753at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, 782at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
754 size_t len, unsigned long flags) 783 size_t len, unsigned long flags)
@@ -779,24 +808,7 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
779 if (unlikely(!len)) 808 if (unlikely(!len))
780 return NULL; 809 return NULL;
781 810
782 /* 811 dwidth = at_xdmac_align_width(chan, src_addr | dst_addr);
783 * Check address alignment to select the greater data width we can use.
784 * Some XDMAC implementations don't provide dword transfer, in this
785 * case selecting dword has the same behavior as selecting word transfers.
786 */
787 if (!((src_addr | dst_addr) & 7)) {
788 dwidth = AT_XDMAC_CC_DWIDTH_DWORD;
789 dev_dbg(chan2dev(chan), "%s: dwidth: double word\n", __func__);
790 } else if (!((src_addr | dst_addr) & 3)) {
791 dwidth = AT_XDMAC_CC_DWIDTH_WORD;
792 dev_dbg(chan2dev(chan), "%s: dwidth: word\n", __func__);
793 } else if (!((src_addr | dst_addr) & 1)) {
794 dwidth = AT_XDMAC_CC_DWIDTH_HALFWORD;
795 dev_dbg(chan2dev(chan), "%s: dwidth: half word\n", __func__);
796 } else {
797 dwidth = AT_XDMAC_CC_DWIDTH_BYTE;
798 dev_dbg(chan2dev(chan), "%s: dwidth: byte\n", __func__);
799 }
800 812
801 /* Prepare descriptors. */ 813 /* Prepare descriptors. */
802 while (remaining_size) { 814 while (remaining_size) {
@@ -826,19 +838,8 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
826 dev_dbg(chan2dev(chan), "%s: xfer_size=%zu\n", __func__, xfer_size); 838 dev_dbg(chan2dev(chan), "%s: xfer_size=%zu\n", __func__, xfer_size);
827 839
828 /* Check remaining length and change data width if needed. */ 840 /* Check remaining length and change data width if needed. */
829 if (!((src_addr | dst_addr | xfer_size) & 7)) { 841 dwidth = at_xdmac_align_width(chan,
830 dwidth = AT_XDMAC_CC_DWIDTH_DWORD; 842 src_addr | dst_addr | xfer_size);
831 dev_dbg(chan2dev(chan), "%s: dwidth: double word\n", __func__);
832 } else if (!((src_addr | dst_addr | xfer_size) & 3)) {
833 dwidth = AT_XDMAC_CC_DWIDTH_WORD;
834 dev_dbg(chan2dev(chan), "%s: dwidth: word\n", __func__);
835 } else if (!((src_addr | dst_addr | xfer_size) & 1)) {
836 dwidth = AT_XDMAC_CC_DWIDTH_HALFWORD;
837 dev_dbg(chan2dev(chan), "%s: dwidth: half word\n", __func__);
838 } else if ((src_addr | dst_addr | xfer_size) & 1) {
839 dwidth = AT_XDMAC_CC_DWIDTH_BYTE;
840 dev_dbg(chan2dev(chan), "%s: dwidth: byte\n", __func__);
841 }
842 chan_cc |= AT_XDMAC_CC_DWIDTH(dwidth); 843 chan_cc |= AT_XDMAC_CC_DWIDTH(dwidth);
843 844
844 ublen = xfer_size >> dwidth; 845 ublen = xfer_size >> dwidth;