diff options
Diffstat (limited to 'drivers/dma/fsldma.c')
-rw-r--r-- | drivers/dma/fsldma.c | 58 |
1 files changed, 44 insertions, 14 deletions
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index cc9a68158d99..ad2f938597e2 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 | ||
60 | static void set_sr(struct fsl_dma_chan *fsl_chan, dma_addr_t val) | 60 | static 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 | ||
65 | static dma_addr_t get_sr(struct fsl_dma_chan *fsl_chan) | 65 | static 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 | } |
@@ -406,6 +406,32 @@ static void fsl_dma_free_chan_resources(struct dma_chan *chan) | |||
406 | dma_pool_destroy(fsl_chan->desc_pool); | 406 | dma_pool_destroy(fsl_chan->desc_pool); |
407 | } | 407 | } |
408 | 408 | ||
409 | static struct dma_async_tx_descriptor * | ||
410 | fsl_dma_prep_interrupt(struct dma_chan *chan) | ||
411 | { | ||
412 | struct fsl_dma_chan *fsl_chan; | ||
413 | struct fsl_desc_sw *new; | ||
414 | |||
415 | if (!chan) | ||
416 | return NULL; | ||
417 | |||
418 | fsl_chan = to_fsl_chan(chan); | ||
419 | |||
420 | new = fsl_dma_alloc_descriptor(fsl_chan); | ||
421 | if (!new) { | ||
422 | dev_err(fsl_chan->dev, "No free memory for link descriptor\n"); | ||
423 | return NULL; | ||
424 | } | ||
425 | |||
426 | new->async_tx.cookie = -EBUSY; | ||
427 | new->async_tx.ack = 0; | ||
428 | |||
429 | /* Set End-of-link to the last link descriptor of new list*/ | ||
430 | set_ld_eol(fsl_chan, new); | ||
431 | |||
432 | return &new->async_tx; | ||
433 | } | ||
434 | |||
409 | static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( | 435 | static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( |
410 | struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src, | 436 | struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src, |
411 | size_t len, unsigned long flags) | 437 | size_t len, unsigned long flags) |
@@ -436,7 +462,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( | |||
436 | dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new); | 462 | dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new); |
437 | #endif | 463 | #endif |
438 | 464 | ||
439 | copy = min(len, FSL_DMA_BCR_MAX_CNT); | 465 | copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT); |
440 | 466 | ||
441 | set_desc_cnt(fsl_chan, &new->hw, copy); | 467 | set_desc_cnt(fsl_chan, &new->hw, copy); |
442 | set_desc_src(fsl_chan, &new->hw, dma_src); | 468 | set_desc_src(fsl_chan, &new->hw, dma_src); |
@@ -513,7 +539,6 @@ static void fsl_chan_ld_cleanup(struct fsl_dma_chan *fsl_chan) | |||
513 | 539 | ||
514 | spin_lock_irqsave(&fsl_chan->desc_lock, flags); | 540 | spin_lock_irqsave(&fsl_chan->desc_lock, flags); |
515 | 541 | ||
516 | fsl_dma_update_completed_cookie(fsl_chan); | ||
517 | dev_dbg(fsl_chan->dev, "chan completed_cookie = %d\n", | 542 | dev_dbg(fsl_chan->dev, "chan completed_cookie = %d\n", |
518 | fsl_chan->completed_cookie); | 543 | fsl_chan->completed_cookie); |
519 | list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) { | 544 | list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) { |
@@ -581,8 +606,8 @@ static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan) | |||
581 | if (ld_node != &fsl_chan->ld_queue) { | 606 | if (ld_node != &fsl_chan->ld_queue) { |
582 | /* Get the ld start address from ld_queue */ | 607 | /* Get the ld start address from ld_queue */ |
583 | next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys; | 608 | next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys; |
584 | dev_dbg(fsl_chan->dev, "xfer LDs staring from 0x%016llx\n", | 609 | dev_dbg(fsl_chan->dev, "xfer LDs staring from %p\n", |
585 | (u64)next_dest_addr); | 610 | (void *)next_dest_addr); |
586 | set_cdar(fsl_chan, next_dest_addr); | 611 | set_cdar(fsl_chan, next_dest_addr); |
587 | dma_start(fsl_chan); | 612 | dma_start(fsl_chan); |
588 | } else { | 613 | } else { |
@@ -662,7 +687,7 @@ static enum dma_status fsl_dma_is_complete(struct dma_chan *chan, | |||
662 | static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data) | 687 | static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data) |
663 | { | 688 | { |
664 | struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data; | 689 | struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data; |
665 | dma_addr_t stat; | 690 | u32 stat; |
666 | 691 | ||
667 | stat = get_sr(fsl_chan); | 692 | stat = get_sr(fsl_chan); |
668 | dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n", | 693 | dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n", |
@@ -681,10 +706,10 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data) | |||
681 | */ | 706 | */ |
682 | if (stat & FSL_DMA_SR_EOSI) { | 707 | if (stat & FSL_DMA_SR_EOSI) { |
683 | dev_dbg(fsl_chan->dev, "event: End-of-segments INT\n"); | 708 | dev_dbg(fsl_chan->dev, "event: End-of-segments INT\n"); |
684 | dev_dbg(fsl_chan->dev, "event: clndar 0x%016llx, " | 709 | dev_dbg(fsl_chan->dev, "event: clndar %p, nlndar %p\n", |
685 | "nlndar 0x%016llx\n", (u64)get_cdar(fsl_chan), | 710 | (void *)get_cdar(fsl_chan), (void *)get_ndar(fsl_chan)); |
686 | (u64)get_ndar(fsl_chan)); | ||
687 | stat &= ~FSL_DMA_SR_EOSI; | 711 | stat &= ~FSL_DMA_SR_EOSI; |
712 | fsl_dma_update_completed_cookie(fsl_chan); | ||
688 | } | 713 | } |
689 | 714 | ||
690 | /* If it current transfer is the end-of-transfer, | 715 | /* If it current transfer is the end-of-transfer, |
@@ -726,12 +751,15 @@ static void dma_do_tasklet(unsigned long data) | |||
726 | fsl_chan_ld_cleanup(fsl_chan); | 751 | fsl_chan_ld_cleanup(fsl_chan); |
727 | } | 752 | } |
728 | 753 | ||
754 | #ifdef FSL_DMA_CALLBACKTEST | ||
729 | static void fsl_dma_callback_test(struct fsl_dma_chan *fsl_chan) | 755 | static void fsl_dma_callback_test(struct fsl_dma_chan *fsl_chan) |
730 | { | 756 | { |
731 | if (fsl_chan) | 757 | if (fsl_chan) |
732 | dev_info(fsl_chan->dev, "selftest: callback is ok!\n"); | 758 | dev_info(fsl_chan->dev, "selftest: callback is ok!\n"); |
733 | } | 759 | } |
760 | #endif | ||
734 | 761 | ||
762 | #ifdef CONFIG_FSL_DMA_SELFTEST | ||
735 | static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan) | 763 | static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan) |
736 | { | 764 | { |
737 | struct dma_chan *chan; | 765 | struct dma_chan *chan; |
@@ -837,9 +865,9 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan) | |||
837 | if (err) { | 865 | if (err) { |
838 | for (i = 0; (*(src + i) == *(dest + i)) && (i < test_size); | 866 | for (i = 0; (*(src + i) == *(dest + i)) && (i < test_size); |
839 | i++); | 867 | i++); |
840 | dev_err(fsl_chan->dev, "selftest: Test failed, data %d/%d is " | 868 | dev_err(fsl_chan->dev, "selftest: Test failed, data %d/%ld is " |
841 | "error! src 0x%x, dest 0x%x\n", | 869 | "error! src 0x%x, dest 0x%x\n", |
842 | i, test_size, *(src + i), *(dest + i)); | 870 | i, (long)test_size, *(src + i), *(dest + i)); |
843 | } | 871 | } |
844 | 872 | ||
845 | free_resources: | 873 | free_resources: |
@@ -848,6 +876,7 @@ out: | |||
848 | kfree(src); | 876 | kfree(src); |
849 | return err; | 877 | return err; |
850 | } | 878 | } |
879 | #endif | ||
851 | 880 | ||
852 | static int __devinit of_fsl_dma_chan_probe(struct of_device *dev, | 881 | static int __devinit of_fsl_dma_chan_probe(struct of_device *dev, |
853 | const struct of_device_id *match) | 882 | const struct of_device_id *match) |
@@ -1008,8 +1037,8 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev, | |||
1008 | } | 1037 | } |
1009 | 1038 | ||
1010 | dev_info(&dev->dev, "Probe the Freescale DMA driver for %s " | 1039 | dev_info(&dev->dev, "Probe the Freescale DMA driver for %s " |
1011 | "controller at 0x%08x...\n", | 1040 | "controller at %p...\n", |
1012 | match->compatible, fdev->reg.start); | 1041 | match->compatible, (void *)fdev->reg.start); |
1013 | fdev->reg_base = ioremap(fdev->reg.start, fdev->reg.end | 1042 | fdev->reg_base = ioremap(fdev->reg.start, fdev->reg.end |
1014 | - fdev->reg.start + 1); | 1043 | - fdev->reg.start + 1); |
1015 | 1044 | ||
@@ -1017,6 +1046,7 @@ static int __devinit of_fsl_dma_probe(struct of_device *dev, | |||
1017 | dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask); | 1046 | dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask); |
1018 | fdev->common.device_alloc_chan_resources = fsl_dma_alloc_chan_resources; | 1047 | fdev->common.device_alloc_chan_resources = fsl_dma_alloc_chan_resources; |
1019 | fdev->common.device_free_chan_resources = fsl_dma_free_chan_resources; | 1048 | fdev->common.device_free_chan_resources = fsl_dma_free_chan_resources; |
1049 | fdev->common.device_prep_dma_interrupt = fsl_dma_prep_interrupt; | ||
1020 | fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy; | 1050 | fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy; |
1021 | fdev->common.device_is_tx_complete = fsl_dma_is_complete; | 1051 | fdev->common.device_is_tx_complete = fsl_dma_is_complete; |
1022 | fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending; | 1052 | fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending; |