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>
This commit is contained in:
committed by
Vinod Koul
parent
ee0fe35c8d
commit
f0816a3688
@@ -749,6 +749,35 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
|
|||||||
return &first->tx_dma_desc;
|
return &first->tx_dma_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u32 at_xdmac_align_width(struct dma_chan *chan, dma_addr_t addr)
|
||||||
|
{
|
||||||
|
u32 width;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check address alignment to select the greater data width we
|
||||||
|
* can use.
|
||||||
|
*
|
||||||
|
* Some XDMAC implementations don't provide dword transfer, in
|
||||||
|
* this case selecting dword has the same behavior as
|
||||||
|
* selecting word transfers.
|
||||||
|
*/
|
||||||
|
if (!(addr & 7)) {
|
||||||
|
width = AT_XDMAC_CC_DWIDTH_DWORD;
|
||||||
|
dev_dbg(chan2dev(chan), "%s: dwidth: double word\n", __func__);
|
||||||
|
} else if (!(addr & 3)) {
|
||||||
|
width = AT_XDMAC_CC_DWIDTH_WORD;
|
||||||
|
dev_dbg(chan2dev(chan), "%s: dwidth: word\n", __func__);
|
||||||
|
} else if (!(addr & 1)) {
|
||||||
|
width = AT_XDMAC_CC_DWIDTH_HALFWORD;
|
||||||
|
dev_dbg(chan2dev(chan), "%s: dwidth: half word\n", __func__);
|
||||||
|
} else {
|
||||||
|
width = AT_XDMAC_CC_DWIDTH_BYTE;
|
||||||
|
dev_dbg(chan2dev(chan), "%s: dwidth: byte\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
static struct dma_async_tx_descriptor *
|
static struct dma_async_tx_descriptor *
|
||||||
at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
|
at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
|
||||||
size_t len, unsigned long flags)
|
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,
|
|||||||
if (unlikely(!len))
|
if (unlikely(!len))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*
|
dwidth = at_xdmac_align_width(chan, src_addr | dst_addr);
|
||||||
* Check address alignment to select the greater data width we can use.
|
|
||||||
* Some XDMAC implementations don't provide dword transfer, in this
|
|
||||||
* case selecting dword has the same behavior as selecting word transfers.
|
|
||||||
*/
|
|
||||||
if (!((src_addr | dst_addr) & 7)) {
|
|
||||||
dwidth = AT_XDMAC_CC_DWIDTH_DWORD;
|
|
||||||
dev_dbg(chan2dev(chan), "%s: dwidth: double word\n", __func__);
|
|
||||||
} else if (!((src_addr | dst_addr) & 3)) {
|
|
||||||
dwidth = AT_XDMAC_CC_DWIDTH_WORD;
|
|
||||||
dev_dbg(chan2dev(chan), "%s: dwidth: word\n", __func__);
|
|
||||||
} else if (!((src_addr | dst_addr) & 1)) {
|
|
||||||
dwidth = AT_XDMAC_CC_DWIDTH_HALFWORD;
|
|
||||||
dev_dbg(chan2dev(chan), "%s: dwidth: half word\n", __func__);
|
|
||||||
} else {
|
|
||||||
dwidth = AT_XDMAC_CC_DWIDTH_BYTE;
|
|
||||||
dev_dbg(chan2dev(chan), "%s: dwidth: byte\n", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare descriptors. */
|
/* Prepare descriptors. */
|
||||||
while (remaining_size) {
|
while (remaining_size) {
|
||||||
@@ -826,19 +838,8 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
|
|||||||
dev_dbg(chan2dev(chan), "%s: xfer_size=%zu\n", __func__, xfer_size);
|
dev_dbg(chan2dev(chan), "%s: xfer_size=%zu\n", __func__, xfer_size);
|
||||||
|
|
||||||
/* Check remaining length and change data width if needed. */
|
/* Check remaining length and change data width if needed. */
|
||||||
if (!((src_addr | dst_addr | xfer_size) & 7)) {
|
dwidth = at_xdmac_align_width(chan,
|
||||||
dwidth = AT_XDMAC_CC_DWIDTH_DWORD;
|
src_addr | dst_addr | xfer_size);
|
||||||
dev_dbg(chan2dev(chan), "%s: dwidth: double word\n", __func__);
|
|
||||||
} else if (!((src_addr | dst_addr | xfer_size) & 3)) {
|
|
||||||
dwidth = AT_XDMAC_CC_DWIDTH_WORD;
|
|
||||||
dev_dbg(chan2dev(chan), "%s: dwidth: word\n", __func__);
|
|
||||||
} else if (!((src_addr | dst_addr | xfer_size) & 1)) {
|
|
||||||
dwidth = AT_XDMAC_CC_DWIDTH_HALFWORD;
|
|
||||||
dev_dbg(chan2dev(chan), "%s: dwidth: half word\n", __func__);
|
|
||||||
} else if ((src_addr | dst_addr | xfer_size) & 1) {
|
|
||||||
dwidth = AT_XDMAC_CC_DWIDTH_BYTE;
|
|
||||||
dev_dbg(chan2dev(chan), "%s: dwidth: byte\n", __func__);
|
|
||||||
}
|
|
||||||
chan_cc |= AT_XDMAC_CC_DWIDTH(dwidth);
|
chan_cc |= AT_XDMAC_CC_DWIDTH(dwidth);
|
||||||
|
|
||||||
ublen = xfer_size >> dwidth;
|
ublen = xfer_size >> dwidth;
|
||||||
|
Reference in New Issue
Block a user