diff options
author | Maxime Ripard <maxime.ripard@free-electrons.com> | 2015-05-07 11:38:09 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2015-05-18 01:29:34 -0400 |
commit | f0816a36887b5b6acb387d8a554c5f5ed4069d33 (patch) | |
tree | 2b8f075e2435a93b54cd859ef5f235e968da0452 /drivers/dma/at_xdmac.c | |
parent | ee0fe35c8dcde29e7f65c34c286378750c075bf3 (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.c | 63 |
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 | ||
752 | static 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 | |||
752 | static struct dma_async_tx_descriptor * | 781 | static struct dma_async_tx_descriptor * |
753 | at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | 782 | at_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; |