Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Daniel Mack and committed by
Vinod Koul
6fc4573c 8fd6aac3

+16 -1
+16 -1
drivers/dma/mmp_pdma.c
··· 109 109 struct list_head chain_pending; /* Link descriptors queue for pending */ 110 110 struct list_head chain_running; /* Link descriptors queue for running */ 111 111 bool idle; /* channel statue machine */ 112 + bool byte_align; 112 113 113 114 struct dma_pool *desc_pool; /* Descriptors pool */ 114 115 }; ··· 143 142 144 143 static void enable_chan(struct mmp_pdma_phy *phy) 145 144 { 146 - u32 reg; 145 + u32 reg, dalgn; 147 146 148 147 if (!phy->vchan) 149 148 return; 150 149 151 150 reg = DRCMR(phy->vchan->drcmr); 152 151 writel(DRCMR_MAPVLD | phy->idx, phy->base + reg); 152 + 153 + dalgn = readl(phy->base + DALGN); 154 + if (phy->vchan->byte_align) 155 + dalgn |= 1 << phy->idx; 156 + else 157 + dalgn &= ~(1 << phy->idx); 158 + writel(dalgn, phy->base + DALGN); 153 159 154 160 reg = (phy->idx << 2) + DCSR; 155 161 writel(readl(phy->base + reg) | DCSR_RUN, ··· 463 455 return NULL; 464 456 465 457 chan = to_mmp_pdma_chan(dchan); 458 + chan->byte_align = false; 466 459 467 460 if (!chan->dir) { 468 461 chan->dir = DMA_MEM_TO_MEM; ··· 480 471 } 481 472 482 473 copy = min_t(size_t, len, PDMA_MAX_DESC_BYTES); 474 + if (dma_src & 0x7 || dma_dst & 0x7) 475 + chan->byte_align = true; 483 476 484 477 new->desc.dcmd = chan->dcmd | (DCMD_LENGTH & copy); 485 478 new->desc.dsadr = dma_src; ··· 541 530 if ((sgl == NULL) || (sg_len == 0)) 542 531 return NULL; 543 532 533 + chan->byte_align = false; 534 + 544 535 for_each_sg(sgl, sg, sg_len, i) { 545 536 addr = sg_dma_address(sg); 546 537 avail = sg_dma_len(sgl); 547 538 548 539 do { 549 540 len = min_t(size_t, avail, PDMA_MAX_DESC_BYTES); 541 + if (addr & 0x7) 542 + chan->byte_align = true; 550 543 551 544 /* allocate and populate the descriptor */ 552 545 new = mmp_pdma_alloc_descriptor(chan);