aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/mpc512x_dma.c
diff options
context:
space:
mode:
authorMario Six <mario.six@gdsys.cc>2016-03-18 09:57:19 -0400
committerVinod Koul <vinod.koul@intel.com>2016-04-04 12:50:10 -0400
commit237ec70903bcf50768138b6c663c67ef1f946cc8 (patch)
tree33e0b685d807f2ce2f1d01876981a304e9e95bdf /drivers/dma/mpc512x_dma.c
parentf55532a0c0b8bb6148f4e07853b876ef73bc69ca (diff)
dmaengine: mpc512x: Fix hanging DMA device transfer for MPC8308
Since the MPC8308 has no external request lines to initiate DMA transfers, all transfers must be triggered by software. Because of this, the current implementation of DMA transfers from and to devices on MPC8308 SoCs using major and minor loops is faulty: After the completion of the first major loop, the DMA engine resets the start flag in the channel's TCD, thus halting the transfer. The driver would have to set the start bit again to trigger the next iteration of the major loop; on MPC512x SoCs, this is done via the external request lines, so in this case, the driver doesn't have to interfer in any way. This has the effect that on MPC8308s, every DMA transfer to or from a device hangs after executing the first major loop. The patch fixes this behavior by using just one major loop for the whole DMA transfer on MPC8308s. Signed-off-by: Mario Six <mario.six@gdsys.cc> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma/mpc512x_dma.c')
-rw-r--r--drivers/dma/mpc512x_dma.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index aae76fb39adc..3a9104a1041c 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -760,21 +760,31 @@ mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
760 tcd->ssize = MPC_DMA_TSIZE_4; 760 tcd->ssize = MPC_DMA_TSIZE_4;
761 tcd->dsize = MPC_DMA_TSIZE_4; 761 tcd->dsize = MPC_DMA_TSIZE_4;
762 762
763 len = sg_dma_len(sg); 763 if (mdma->is_mpc8308) {
764 tcd->nbytes = tcd_nunits * 4; 764 tcd->nbytes = sg_dma_len(sg);
765 if (!IS_ALIGNED(len, tcd->nbytes)) 765 if (!IS_ALIGNED(tcd->nbytes, 4))
766 goto err_prep; 766 goto err_prep;
767 767
768 iter = len / tcd->nbytes; 768 /* No major loops for MPC8303 */
769 if (iter >= 1 << 15) { 769 tcd->biter = 1;
770 /* len is too big */ 770 tcd->citer = 1;
771 goto err_prep; 771 } else {
772 len = sg_dma_len(sg);
773 tcd->nbytes = tcd_nunits * 4;
774 if (!IS_ALIGNED(len, tcd->nbytes))
775 goto err_prep;
776
777 iter = len / tcd->nbytes;
778 if (iter >= 1 << 15) {
779 /* len is too big */
780 goto err_prep;
781 }
782 /* citer_linkch contains the high bits of iter */
783 tcd->biter = iter & 0x1ff;
784 tcd->biter_linkch = iter >> 9;
785 tcd->citer = tcd->biter;
786 tcd->citer_linkch = tcd->biter_linkch;
772 } 787 }
773 /* citer_linkch contains the high bits of iter */
774 tcd->biter = iter & 0x1ff;
775 tcd->biter_linkch = iter >> 9;
776 tcd->citer = tcd->biter;
777 tcd->citer_linkch = tcd->biter_linkch;
778 788
779 tcd->e_sg = 0; 789 tcd->e_sg = 0;
780 tcd->d_req = 1; 790 tcd->d_req = 1;