mirror of
https://github.com/torvalds/linux.git
synced 2024-11-28 23:21:31 +00:00
dma: mmp_pdma: add support for byte-aligned transfers
The PXA DMA controller has a DALGN register which allows for byte-aligned DMA transfers. Use it in case any of the transfer descriptors is not aligned to a mask of ~0x7. Signed-off-by: Daniel Mack <zonque@gmail.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
This commit is contained in:
parent
8fd6aac3a8
commit
6fc4573c4e
@ -109,6 +109,7 @@ struct mmp_pdma_chan {
|
||||
struct list_head chain_pending; /* Link descriptors queue for pending */
|
||||
struct list_head chain_running; /* Link descriptors queue for running */
|
||||
bool idle; /* channel statue machine */
|
||||
bool byte_align;
|
||||
|
||||
struct dma_pool *desc_pool; /* Descriptors pool */
|
||||
};
|
||||
@ -142,7 +143,7 @@ static void set_desc(struct mmp_pdma_phy *phy, dma_addr_t addr)
|
||||
|
||||
static void enable_chan(struct mmp_pdma_phy *phy)
|
||||
{
|
||||
u32 reg;
|
||||
u32 reg, dalgn;
|
||||
|
||||
if (!phy->vchan)
|
||||
return;
|
||||
@ -150,6 +151,13 @@ static void enable_chan(struct mmp_pdma_phy *phy)
|
||||
reg = DRCMR(phy->vchan->drcmr);
|
||||
writel(DRCMR_MAPVLD | phy->idx, phy->base + reg);
|
||||
|
||||
dalgn = readl(phy->base + DALGN);
|
||||
if (phy->vchan->byte_align)
|
||||
dalgn |= 1 << phy->idx;
|
||||
else
|
||||
dalgn &= ~(1 << phy->idx);
|
||||
writel(dalgn, phy->base + DALGN);
|
||||
|
||||
reg = (phy->idx << 2) + DCSR;
|
||||
writel(readl(phy->base + reg) | DCSR_RUN,
|
||||
phy->base + reg);
|
||||
@ -455,6 +463,7 @@ mmp_pdma_prep_memcpy(struct dma_chan *dchan,
|
||||
return NULL;
|
||||
|
||||
chan = to_mmp_pdma_chan(dchan);
|
||||
chan->byte_align = false;
|
||||
|
||||
if (!chan->dir) {
|
||||
chan->dir = DMA_MEM_TO_MEM;
|
||||
@ -471,6 +480,8 @@ mmp_pdma_prep_memcpy(struct dma_chan *dchan,
|
||||
}
|
||||
|
||||
copy = min_t(size_t, len, PDMA_MAX_DESC_BYTES);
|
||||
if (dma_src & 0x7 || dma_dst & 0x7)
|
||||
chan->byte_align = true;
|
||||
|
||||
new->desc.dcmd = chan->dcmd | (DCMD_LENGTH & copy);
|
||||
new->desc.dsadr = dma_src;
|
||||
@ -530,12 +541,16 @@ mmp_pdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
|
||||
if ((sgl == NULL) || (sg_len == 0))
|
||||
return NULL;
|
||||
|
||||
chan->byte_align = false;
|
||||
|
||||
for_each_sg(sgl, sg, sg_len, i) {
|
||||
addr = sg_dma_address(sg);
|
||||
avail = sg_dma_len(sgl);
|
||||
|
||||
do {
|
||||
len = min_t(size_t, avail, PDMA_MAX_DESC_BYTES);
|
||||
if (addr & 0x7)
|
||||
chan->byte_align = true;
|
||||
|
||||
/* allocate and populate the descriptor */
|
||||
new = mmp_pdma_alloc_descriptor(chan);
|
||||
|
Loading…
Reference in New Issue
Block a user