diff options
Diffstat (limited to 'drivers/dma/fsldma.c')
-rw-r--r-- | drivers/dma/fsldma.c | 57 |
1 files changed, 29 insertions, 28 deletions
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index df163687c91..054eabffc18 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -412,7 +412,7 @@ static void fsl_dma_free_chan_resources(struct dma_chan *chan) } static struct dma_async_tx_descriptor * -fsl_dma_prep_interrupt(struct dma_chan *chan) +fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags) { struct fsl_dma_chan *fsl_chan; struct fsl_desc_sw *new; @@ -429,7 +429,7 @@ fsl_dma_prep_interrupt(struct dma_chan *chan) } new->async_tx.cookie = -EBUSY; - new->async_tx.ack = 0; + new->async_tx.flags = flags; /* Insert the link descriptor to the LD ring */ list_add_tail(&new->node, &new->async_tx.tx_list); @@ -482,7 +482,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( set_desc_next(fsl_chan, &prev->hw, new->async_tx.phys); new->async_tx.cookie = 0; - new->async_tx.ack = 1; + async_tx_ack(&new->async_tx); prev = new; len -= copy; @@ -493,7 +493,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( list_add_tail(&new->node, &first->async_tx.tx_list); } while (len); - new->async_tx.ack = 0; /* client is in control of this ack */ + new->async_tx.flags = flags; /* client is in control of this ack */ new->async_tx.cookie = -EBUSY; /* Set End-of-link to the last link descriptor of new list*/ @@ -658,13 +658,6 @@ static void fsl_dma_memcpy_issue_pending(struct dma_chan *chan) fsl_chan_xfer_ld_queue(fsl_chan); } -static void fsl_dma_dependency_added(struct dma_chan *chan) -{ - struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan); - - fsl_chan_ld_cleanup(fsl_chan); -} - /** * fsl_dma_is_complete - Determine the DMA status * @fsl_chan : Freescale DMA channel @@ -696,6 +689,8 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data) { struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data; u32 stat; + int update_cookie = 0; + int xfer_ld_q = 0; stat = get_sr(fsl_chan); dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n", @@ -720,8 +715,8 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data) * Now, update the completed cookie, and continue the * next uncompleted transfer. */ - fsl_dma_update_completed_cookie(fsl_chan); - fsl_chan_xfer_ld_queue(fsl_chan); + update_cookie = 1; + xfer_ld_q = 1; } stat &= ~FSL_DMA_SR_PE; } @@ -734,19 +729,33 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data) dev_dbg(fsl_chan->dev, "event: clndar %p, nlndar %p\n", (void *)get_cdar(fsl_chan), (void *)get_ndar(fsl_chan)); stat &= ~FSL_DMA_SR_EOSI; - fsl_dma_update_completed_cookie(fsl_chan); + update_cookie = 1; + } + + /* For MPC8349, EOCDI event need to update cookie + * and start the next transfer if it exist. + */ + if (stat & FSL_DMA_SR_EOCDI) { + dev_dbg(fsl_chan->dev, "event: End-of-Chain link INT\n"); + stat &= ~FSL_DMA_SR_EOCDI; + update_cookie = 1; + xfer_ld_q = 1; } /* If it current transfer is the end-of-transfer, * we should clear the Channel Start bit for * prepare next transfer. */ - if (stat & (FSL_DMA_SR_EOLNI | FSL_DMA_SR_EOCDI)) { + if (stat & FSL_DMA_SR_EOLNI) { dev_dbg(fsl_chan->dev, "event: End-of-link INT\n"); stat &= ~FSL_DMA_SR_EOLNI; - fsl_chan_xfer_ld_queue(fsl_chan); + xfer_ld_q = 1; } + if (update_cookie) + fsl_dma_update_completed_cookie(fsl_chan); + if (xfer_ld_q) + fsl_chan_xfer_ld_queue(fsl_chan); if (stat) dev_dbg(fsl_chan->dev, "event: unhandled sr 0x%02x\n", stat); @@ -776,15 +785,13 @@ static void dma_do_tasklet(unsigned long data) fsl_chan_ld_cleanup(fsl_chan); } -#ifdef FSL_DMA_CALLBACKTEST -static void fsl_dma_callback_test(struct fsl_dma_chan *fsl_chan) +static void fsl_dma_callback_test(void *param) { + struct fsl_dma_chan *fsl_chan = param; if (fsl_chan) - dev_info(fsl_chan->dev, "selftest: callback is ok!\n"); + dev_dbg(fsl_chan->dev, "selftest: callback is ok!\n"); } -#endif -#ifdef CONFIG_FSL_DMA_SELFTEST static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan) { struct dma_chan *chan; @@ -867,7 +874,7 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan) async_tx_ack(tx3); /* Interrupt tx test */ - tx1 = fsl_dma_prep_interrupt(chan); + tx1 = fsl_dma_prep_interrupt(chan, 0); async_tx_ack(tx1); cookie = fsl_dma_tx_submit(tx1); @@ -875,13 +882,11 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan) cookie = fsl_dma_tx_submit(tx3); cookie = fsl_dma_tx_submit(tx2); -#ifdef FSL_DMA_CALLBACKTEST if (dma_has_cap(DMA_INTERRUPT, ((struct fsl_dma_device *) dev_get_drvdata(fsl_chan->dev->parent))->common.cap_mask)) { tx3->callback = fsl_dma_callback_test; tx3->callback_param = fsl_chan; } -#endif fsl_dma_memcpy_issue_pending(chan); msleep(2); @@ -906,7 +911,6 @@ out: kfree(src); return err; } -#endif static int __devinit of_fsl_dma_chan_probe(struct of_device *dev, const struct of_device_id *match) @@ -997,11 +1001,9 @@ static int __devinit of_fsl_dma_chan_probe(struct of_device *dev, } } -#ifdef CONFIG_FSL_DMA_SELFTEST err = fsl_dma_self_test(new_fsl_chan); if (err) goto err; -#endif dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id, match->compatible, new_fsl_chan->irq); @@ -1080,7 +1082,6 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev, fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy; fdev->common.device_is_tx_complete = fsl_dma_is_complete; fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending; - fdev->common.device_dependency_added = fsl_dma_dependency_added; fdev->common.dev = &dev->dev; irq = irq_of_parse_and_map(dev->node, 0); |