aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/fsldma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/fsldma.c')
-rw-r--r--drivers/dma/fsldma.c88
1 files changed, 74 insertions, 14 deletions
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index cc9a68158d99..72692309398a 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -57,12 +57,12 @@ static void dma_init(struct fsl_dma_chan *fsl_chan)
57 57
58} 58}
59 59
60static void set_sr(struct fsl_dma_chan *fsl_chan, dma_addr_t val) 60static void set_sr(struct fsl_dma_chan *fsl_chan, u32 val)
61{ 61{
62 DMA_OUT(fsl_chan, &fsl_chan->reg_base->sr, val, 32); 62 DMA_OUT(fsl_chan, &fsl_chan->reg_base->sr, val, 32);
63} 63}
64 64
65static dma_addr_t get_sr(struct fsl_dma_chan *fsl_chan) 65static u32 get_sr(struct fsl_dma_chan *fsl_chan)
66{ 66{
67 return DMA_IN(fsl_chan, &fsl_chan->reg_base->sr, 32); 67 return DMA_IN(fsl_chan, &fsl_chan->reg_base->sr, 32);
68} 68}
@@ -123,6 +123,11 @@ static dma_addr_t get_ndar(struct fsl_dma_chan *fsl_chan)
123 return DMA_IN(fsl_chan, &fsl_chan->reg_base->ndar, 64); 123 return DMA_IN(fsl_chan, &fsl_chan->reg_base->ndar, 64);
124} 124}
125 125
126static u32 get_bcr(struct fsl_dma_chan *fsl_chan)
127{
128 return DMA_IN(fsl_chan, &fsl_chan->reg_base->bcr, 32);
129}
130
126static int dma_is_idle(struct fsl_dma_chan *fsl_chan) 131static int dma_is_idle(struct fsl_dma_chan *fsl_chan)
127{ 132{
128 u32 sr = get_sr(fsl_chan); 133 u32 sr = get_sr(fsl_chan);
@@ -406,6 +411,35 @@ static void fsl_dma_free_chan_resources(struct dma_chan *chan)
406 dma_pool_destroy(fsl_chan->desc_pool); 411 dma_pool_destroy(fsl_chan->desc_pool);
407} 412}
408 413
414static struct dma_async_tx_descriptor *
415fsl_dma_prep_interrupt(struct dma_chan *chan)
416{
417 struct fsl_dma_chan *fsl_chan;
418 struct fsl_desc_sw *new;
419
420 if (!chan)
421 return NULL;
422
423 fsl_chan = to_fsl_chan(chan);
424
425 new = fsl_dma_alloc_descriptor(fsl_chan);
426 if (!new) {
427 dev_err(fsl_chan->dev, "No free memory for link descriptor\n");
428 return NULL;
429 }
430
431 new->async_tx.cookie = -EBUSY;
432 new->async_tx.ack = 0;
433
434 /* Insert the link descriptor to the LD ring */
435 list_add_tail(&new->node, &new->async_tx.tx_list);
436
437 /* Set End-of-link to the last link descriptor of new list*/
438 set_ld_eol(fsl_chan, new);
439
440 return &new->async_tx;
441}
442
409static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( 443static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
410 struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src, 444 struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
411 size_t len, unsigned long flags) 445 size_t len, unsigned long flags)
@@ -436,7 +470,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
436 dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new); 470 dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);
437#endif 471#endif
438 472
439 copy = min(len, FSL_DMA_BCR_MAX_CNT); 473 copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT);
440 474
441 set_desc_cnt(fsl_chan, &new->hw, copy); 475 set_desc_cnt(fsl_chan, &new->hw, copy);
442 set_desc_src(fsl_chan, &new->hw, dma_src); 476 set_desc_src(fsl_chan, &new->hw, dma_src);
@@ -513,7 +547,6 @@ static void fsl_chan_ld_cleanup(struct fsl_dma_chan *fsl_chan)
513 547
514 spin_lock_irqsave(&fsl_chan->desc_lock, flags); 548 spin_lock_irqsave(&fsl_chan->desc_lock, flags);
515 549
516 fsl_dma_update_completed_cookie(fsl_chan);
517 dev_dbg(fsl_chan->dev, "chan completed_cookie = %d\n", 550 dev_dbg(fsl_chan->dev, "chan completed_cookie = %d\n",
518 fsl_chan->completed_cookie); 551 fsl_chan->completed_cookie);
519 list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) { 552 list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) {
@@ -581,8 +614,8 @@ static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan)
581 if (ld_node != &fsl_chan->ld_queue) { 614 if (ld_node != &fsl_chan->ld_queue) {
582 /* Get the ld start address from ld_queue */ 615 /* Get the ld start address from ld_queue */
583 next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys; 616 next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys;
584 dev_dbg(fsl_chan->dev, "xfer LDs staring from 0x%016llx\n", 617 dev_dbg(fsl_chan->dev, "xfer LDs staring from %p\n",
585 (u64)next_dest_addr); 618 (void *)next_dest_addr);
586 set_cdar(fsl_chan, next_dest_addr); 619 set_cdar(fsl_chan, next_dest_addr);
587 dma_start(fsl_chan); 620 dma_start(fsl_chan);
588 } else { 621 } else {
@@ -662,7 +695,7 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
662static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data) 695static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
663{ 696{
664 struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data; 697 struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
665 dma_addr_t stat; 698 u32 stat;
666 699
667 stat = get_sr(fsl_chan); 700 stat = get_sr(fsl_chan);
668 dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n", 701 dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n",
@@ -676,15 +709,32 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
676 if (stat & FSL_DMA_SR_TE) 709 if (stat & FSL_DMA_SR_TE)
677 dev_err(fsl_chan->dev, "Transfer Error!\n"); 710 dev_err(fsl_chan->dev, "Transfer Error!\n");
678 711
712 /* Programming Error
713 * The DMA_INTERRUPT async_tx is a NULL transfer, which will
714 * triger a PE interrupt.
715 */
716 if (stat & FSL_DMA_SR_PE) {
717 dev_dbg(fsl_chan->dev, "event: Programming Error INT\n");
718 if (get_bcr(fsl_chan) == 0) {
719 /* BCR register is 0, this is a DMA_INTERRUPT async_tx.
720 * Now, update the completed cookie, and continue the
721 * next uncompleted transfer.
722 */
723 fsl_dma_update_completed_cookie(fsl_chan);
724 fsl_chan_xfer_ld_queue(fsl_chan);
725 }
726 stat &= ~FSL_DMA_SR_PE;
727 }
728
679 /* If the link descriptor segment transfer finishes, 729 /* If the link descriptor segment transfer finishes,
680 * we will recycle the used descriptor. 730 * we will recycle the used descriptor.
681 */ 731 */
682 if (stat & FSL_DMA_SR_EOSI) { 732 if (stat & FSL_DMA_SR_EOSI) {
683 dev_dbg(fsl_chan->dev, "event: End-of-segments INT\n"); 733 dev_dbg(fsl_chan->dev, "event: End-of-segments INT\n");
684 dev_dbg(fsl_chan->dev, "event: clndar 0x%016llx, " 734 dev_dbg(fsl_chan->dev, "event: clndar %p, nlndar %p\n",
685 "nlndar 0x%016llx\n", (u64)get_cdar(fsl_chan), 735 (void *)get_cdar(fsl_chan), (void *)get_ndar(fsl_chan));
686 (u64)get_ndar(fsl_chan));
687 stat &= ~FSL_DMA_SR_EOSI; 736 stat &= ~FSL_DMA_SR_EOSI;
737 fsl_dma_update_completed_cookie(fsl_chan);
688 } 738 }
689 739
690 /* If it current transfer is the end-of-transfer, 740 /* If it current transfer is the end-of-transfer,
@@ -726,12 +776,15 @@ static void dma_do_tasklet(unsigned long data)
726 fsl_chan_ld_cleanup(fsl_chan); 776 fsl_chan_ld_cleanup(fsl_chan);
727} 777}
728 778
779#ifdef FSL_DMA_CALLBACKTEST
729static void fsl_dma_callback_test(struct fsl_dma_chan *fsl_chan) 780static void fsl_dma_callback_test(struct fsl_dma_chan *fsl_chan)
730{ 781{
731 if (fsl_chan) 782 if (fsl_chan)
732 dev_info(fsl_chan->dev, "selftest: callback is ok!\n"); 783 dev_info(fsl_chan->dev, "selftest: callback is ok!\n");
733} 784}
785#endif
734 786
787#ifdef CONFIG_FSL_DMA_SELFTEST
735static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan) 788static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
736{ 789{
737 struct dma_chan *chan; 790 struct dma_chan *chan;
@@ -813,6 +866,11 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
813 tx3 = fsl_dma_prep_memcpy(chan, dma_dest, dma_src, test_size / 4, 0); 866 tx3 = fsl_dma_prep_memcpy(chan, dma_dest, dma_src, test_size / 4, 0);
814 async_tx_ack(tx3); 867 async_tx_ack(tx3);
815 868
869 /* Interrupt tx test */
870 tx1 = fsl_dma_prep_interrupt(chan);
871 async_tx_ack(tx1);
872 cookie = fsl_dma_tx_submit(tx1);
873
816 /* Test exchanging the prepared tx sort */ 874 /* Test exchanging the prepared tx sort */
817 cookie = fsl_dma_tx_submit(tx3); 875 cookie = fsl_dma_tx_submit(tx3);
818 cookie = fsl_dma_tx_submit(tx2); 876 cookie = fsl_dma_tx_submit(tx2);
@@ -837,9 +895,9 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
837 if (err) { 895 if (err) {
838 for (i = 0; (*(src + i) == *(dest + i)) && (i < test_size); 896 for (i = 0; (*(src + i) == *(dest + i)) && (i < test_size);
839 i++); 897 i++);
840 dev_err(fsl_chan->dev, "selftest: Test failed, data %d/%d is " 898 dev_err(fsl_chan->dev, "selftest: Test failed, data %d/%ld is "
841 "error! src 0x%x, dest 0x%x\n", 899 "error! src 0x%x, dest 0x%x\n",
842 i, test_size, *(src + i), *(dest + i)); 900 i, (long)test_size, *(src + i), *(dest + i));
843 } 901 }
844 902
845free_resources: 903free_resources:
@@ -848,6 +906,7 @@ out:
848 kfree(src); 906 kfree(src);
849 return err; 907 return err;
850} 908}
909#endif
851 910
852static int __devinit of_fsl_dma_chan_probe(struct of_device *dev, 911static int __devinit of_fsl_dma_chan_probe(struct of_device *dev,
853 const struct of_device_id *match) 912 const struct of_device_id *match)
@@ -1008,8 +1067,8 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
1008 } 1067 }
1009 1068
1010 dev_info(&dev->dev, "Probe the Freescale DMA driver for %s " 1069 dev_info(&dev->dev, "Probe the Freescale DMA driver for %s "
1011 "controller at 0x%08x...\n", 1070 "controller at %p...\n",
1012 match->compatible, fdev->reg.start); 1071 match->compatible, (void *)fdev->reg.start);
1013 fdev->reg_base = ioremap(fdev->reg.start, fdev->reg.end 1072 fdev->reg_base = ioremap(fdev->reg.start, fdev->reg.end
1014 - fdev->reg.start + 1); 1073 - fdev->reg.start + 1);
1015 1074
@@ -1017,6 +1076,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev,
1017 dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask); 1076 dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
1018 fdev->common.device_alloc_chan_resources = fsl_dma_alloc_chan_resources; 1077 fdev->common.device_alloc_chan_resources = fsl_dma_alloc_chan_resources;
1019 fdev->common.device_free_chan_resources = fsl_dma_free_chan_resources; 1078 fdev->common.device_free_chan_resources = fsl_dma_free_chan_resources;
1079 fdev->common.device_prep_dma_interrupt = fsl_dma_prep_interrupt;
1020 fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy; 1080 fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy;
1021 fdev->common.device_is_tx_complete = fsl_dma_is_complete; 1081 fdev->common.device_is_tx_complete = fsl_dma_is_complete;
1022 fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending; 1082 fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;