diff options
author | Vinod Koul <vinod.koul@intel.com> | 2014-12-05 09:01:32 -0500 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2014-12-05 09:01:32 -0500 |
commit | 939b6ef378bfb6fd9cff61a1f3afa17e84ea0884 (patch) | |
tree | a01ba87fda921e8e60e4d938b0cf0d8d7fd37868 | |
parent | af2d3139e19fd7da9a5d300a83812616b2d6694c (diff) | |
parent | fef4cbf2ab830fcd695d892927386ad9ccc46339 (diff) |
Merge branch 'topic/at_xdmac' into for-linus
-rw-r--r-- | Documentation/devicetree/bindings/dma/atmel-xdma.txt | 2 | ||||
-rw-r--r-- | drivers/dma/Kconfig | 2 | ||||
-rw-r--r-- | drivers/dma/at_xdmac.c | 74 |
3 files changed, 46 insertions, 32 deletions
diff --git a/Documentation/devicetree/bindings/dma/atmel-xdma.txt b/Documentation/devicetree/bindings/dma/atmel-xdma.txt index e75c128c53fa..0eb2b3207e08 100644 --- a/Documentation/devicetree/bindings/dma/atmel-xdma.txt +++ b/Documentation/devicetree/bindings/dma/atmel-xdma.txt | |||
@@ -22,7 +22,7 @@ dma1: dma-controller@f0004000 { | |||
22 | compatible = "atmel,sama5d4-dma"; | 22 | compatible = "atmel,sama5d4-dma"; |
23 | reg = <0xf0004000 0x200>; | 23 | reg = <0xf0004000 0x200>; |
24 | interrupts = <50 4 0>; | 24 | interrupts = <50 4 0>; |
25 | #dma-cells = <2>; | 25 | #dma-cells = <1>; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | 28 | ||
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index aef8b9dd4db6..f2b2c4e87aef 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -109,7 +109,7 @@ config AT_HDMAC | |||
109 | 109 | ||
110 | config AT_XDMAC | 110 | config AT_XDMAC |
111 | tristate "Atmel XDMA support" | 111 | tristate "Atmel XDMA support" |
112 | depends on (ARCH_AT91 || COMPILE_TEST) | 112 | depends on ARCH_AT91 |
113 | select DMA_ENGINE | 113 | select DMA_ENGINE |
114 | help | 114 | help |
115 | Support the Atmel XDMA controller. | 115 | Support the Atmel XDMA controller. |
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index 4e9b023990ae..b60d77a22df6 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c | |||
@@ -562,6 +562,7 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
562 | struct scatterlist *sg; | 562 | struct scatterlist *sg; |
563 | int i; | 563 | int i; |
564 | u32 cfg; | 564 | u32 cfg; |
565 | unsigned int xfer_size = 0; | ||
565 | 566 | ||
566 | if (!sgl) | 567 | if (!sgl) |
567 | return NULL; | 568 | return NULL; |
@@ -619,15 +620,15 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
619 | | (i == sg_len - 1 ? 0 : AT_XDMAC_MBR_UBC_NDE) /* descriptor fetch */ | 620 | | (i == sg_len - 1 ? 0 : AT_XDMAC_MBR_UBC_NDE) /* descriptor fetch */ |
620 | | len / (1 << at_xdmac_get_dwidth(cfg)); /* microblock length */ | 621 | | len / (1 << at_xdmac_get_dwidth(cfg)); /* microblock length */ |
621 | dev_dbg(chan2dev(chan), | 622 | dev_dbg(chan2dev(chan), |
622 | "%s: lld: mbr_sa=0x%08x, mbr_da=0x%08x, mbr_ubc=0x%08x\n", | 623 | "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n", |
623 | __func__, desc->lld.mbr_sa, desc->lld.mbr_da, desc->lld.mbr_ubc); | 624 | __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc); |
624 | 625 | ||
625 | /* Chain lld. */ | 626 | /* Chain lld. */ |
626 | if (prev) { | 627 | if (prev) { |
627 | prev->lld.mbr_nda = desc->tx_dma_desc.phys; | 628 | prev->lld.mbr_nda = desc->tx_dma_desc.phys; |
628 | dev_dbg(chan2dev(chan), | 629 | dev_dbg(chan2dev(chan), |
629 | "%s: chain lld: prev=0x%p, mbr_nda=0x%08x\n", | 630 | "%s: chain lld: prev=0x%p, mbr_nda=%pad\n", |
630 | __func__, prev, prev->lld.mbr_nda); | 631 | __func__, prev, &prev->lld.mbr_nda); |
631 | } | 632 | } |
632 | 633 | ||
633 | prev = desc; | 634 | prev = desc; |
@@ -637,12 +638,13 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
637 | dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", | 638 | dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", |
638 | __func__, desc, first); | 639 | __func__, desc, first); |
639 | list_add_tail(&desc->desc_node, &first->descs_list); | 640 | list_add_tail(&desc->desc_node, &first->descs_list); |
641 | xfer_size += len; | ||
640 | } | 642 | } |
641 | 643 | ||
642 | spin_unlock_bh(&atchan->lock); | 644 | spin_unlock_bh(&atchan->lock); |
643 | 645 | ||
644 | first->tx_dma_desc.flags = flags; | 646 | first->tx_dma_desc.flags = flags; |
645 | first->xfer_size = sg_len; | 647 | first->xfer_size = xfer_size; |
646 | first->direction = direction; | 648 | first->direction = direction; |
647 | 649 | ||
648 | return &first->tx_dma_desc; | 650 | return &first->tx_dma_desc; |
@@ -660,8 +662,8 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, | |||
660 | int i; | 662 | int i; |
661 | u32 cfg; | 663 | u32 cfg; |
662 | 664 | ||
663 | dev_dbg(chan2dev(chan), "%s: buf_addr=0x%08x, buf_len=%d, period_len=%d, dir=%s, flags=0x%lx\n", | 665 | dev_dbg(chan2dev(chan), "%s: buf_addr=%pad, buf_len=%zd, period_len=%zd, dir=%s, flags=0x%lx\n", |
664 | __func__, buf_addr, buf_len, period_len, | 666 | __func__, &buf_addr, buf_len, period_len, |
665 | direction == DMA_MEM_TO_DEV ? "mem2per" : "per2mem", flags); | 667 | direction == DMA_MEM_TO_DEV ? "mem2per" : "per2mem", flags); |
666 | 668 | ||
667 | if (!is_slave_direction(direction)) { | 669 | if (!is_slave_direction(direction)) { |
@@ -688,8 +690,8 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, | |||
688 | } | 690 | } |
689 | spin_unlock_bh(&atchan->lock); | 691 | spin_unlock_bh(&atchan->lock); |
690 | dev_dbg(chan2dev(chan), | 692 | dev_dbg(chan2dev(chan), |
691 | "%s: desc=0x%p, tx_dma_desc.phys=0x%08x\n", | 693 | "%s: desc=0x%p, tx_dma_desc.phys=%pad\n", |
692 | __func__, desc, desc->tx_dma_desc.phys); | 694 | __func__, desc, &desc->tx_dma_desc.phys); |
693 | 695 | ||
694 | if (direction == DMA_DEV_TO_MEM) { | 696 | if (direction == DMA_DEV_TO_MEM) { |
695 | desc->lld.mbr_sa = atchan->per_src_addr; | 697 | desc->lld.mbr_sa = atchan->per_src_addr; |
@@ -699,7 +701,7 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, | |||
699 | desc->lld.mbr_sa = buf_addr + i * period_len; | 701 | desc->lld.mbr_sa = buf_addr + i * period_len; |
700 | desc->lld.mbr_da = atchan->per_dst_addr; | 702 | desc->lld.mbr_da = atchan->per_dst_addr; |
701 | cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG]; | 703 | cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG]; |
702 | }; | 704 | } |
703 | desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV1 | 705 | desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV1 |
704 | | AT_XDMAC_MBR_UBC_NDEN | 706 | | AT_XDMAC_MBR_UBC_NDEN |
705 | | AT_XDMAC_MBR_UBC_NSEN | 707 | | AT_XDMAC_MBR_UBC_NSEN |
@@ -707,15 +709,15 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, | |||
707 | | period_len >> at_xdmac_get_dwidth(cfg); | 709 | | period_len >> at_xdmac_get_dwidth(cfg); |
708 | 710 | ||
709 | dev_dbg(chan2dev(chan), | 711 | dev_dbg(chan2dev(chan), |
710 | "%s: lld: mbr_sa=0x%08x, mbr_da=0x%08x, mbr_ubc=0x%08x\n", | 712 | "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n", |
711 | __func__, desc->lld.mbr_sa, desc->lld.mbr_da, desc->lld.mbr_ubc); | 713 | __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc); |
712 | 714 | ||
713 | /* Chain lld. */ | 715 | /* Chain lld. */ |
714 | if (prev) { | 716 | if (prev) { |
715 | prev->lld.mbr_nda = desc->tx_dma_desc.phys; | 717 | prev->lld.mbr_nda = desc->tx_dma_desc.phys; |
716 | dev_dbg(chan2dev(chan), | 718 | dev_dbg(chan2dev(chan), |
717 | "%s: chain lld: prev=0x%p, mbr_nda=0x%08x\n", | 719 | "%s: chain lld: prev=0x%p, mbr_nda=%pad\n", |
718 | __func__, prev, prev->lld.mbr_nda); | 720 | __func__, prev, &prev->lld.mbr_nda); |
719 | } | 721 | } |
720 | 722 | ||
721 | prev = desc; | 723 | prev = desc; |
@@ -729,8 +731,8 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, | |||
729 | 731 | ||
730 | prev->lld.mbr_nda = first->tx_dma_desc.phys; | 732 | prev->lld.mbr_nda = first->tx_dma_desc.phys; |
731 | dev_dbg(chan2dev(chan), | 733 | dev_dbg(chan2dev(chan), |
732 | "%s: chain lld: prev=0x%p, mbr_nda=0x%08x\n", | 734 | "%s: chain lld: prev=0x%p, mbr_nda=%pad\n", |
733 | __func__, prev, prev->lld.mbr_nda); | 735 | __func__, prev, &prev->lld.mbr_nda); |
734 | first->tx_dma_desc.flags = flags; | 736 | first->tx_dma_desc.flags = flags; |
735 | first->xfer_size = buf_len; | 737 | first->xfer_size = buf_len; |
736 | first->direction = direction; | 738 | first->direction = direction; |
@@ -762,8 +764,8 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
762 | | AT_XDMAC_CC_MBSIZE_SIXTEEN | 764 | | AT_XDMAC_CC_MBSIZE_SIXTEEN |
763 | | AT_XDMAC_CC_TYPE_MEM_TRAN; | 765 | | AT_XDMAC_CC_TYPE_MEM_TRAN; |
764 | 766 | ||
765 | dev_dbg(chan2dev(chan), "%s: src=0x%08x, dest=0x%08x, len=%d, flags=0x%lx\n", | 767 | dev_dbg(chan2dev(chan), "%s: src=%pad, dest=%pad, len=%zd, flags=0x%lx\n", |
766 | __func__, src, dest, len, flags); | 768 | __func__, &src, &dest, len, flags); |
767 | 769 | ||
768 | if (unlikely(!len)) | 770 | if (unlikely(!len)) |
769 | return NULL; | 771 | return NULL; |
@@ -791,7 +793,7 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
791 | while (remaining_size) { | 793 | while (remaining_size) { |
792 | struct at_xdmac_desc *desc = NULL; | 794 | struct at_xdmac_desc *desc = NULL; |
793 | 795 | ||
794 | dev_dbg(chan2dev(chan), "%s: remaining_size=%u\n", __func__, remaining_size); | 796 | dev_dbg(chan2dev(chan), "%s: remaining_size=%zu\n", __func__, remaining_size); |
795 | 797 | ||
796 | spin_lock_bh(&atchan->lock); | 798 | spin_lock_bh(&atchan->lock); |
797 | desc = at_xdmac_get_desc(atchan); | 799 | desc = at_xdmac_get_desc(atchan); |
@@ -812,7 +814,7 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
812 | else | 814 | else |
813 | xfer_size = remaining_size; | 815 | xfer_size = remaining_size; |
814 | 816 | ||
815 | dev_dbg(chan2dev(chan), "%s: xfer_size=%u\n", __func__, xfer_size); | 817 | dev_dbg(chan2dev(chan), "%s: xfer_size=%zu\n", __func__, xfer_size); |
816 | 818 | ||
817 | /* Check remaining length and change data width if needed. */ | 819 | /* Check remaining length and change data width if needed. */ |
818 | if (!((src_addr | dst_addr | xfer_size) & 7)) { | 820 | if (!((src_addr | dst_addr | xfer_size) & 7)) { |
@@ -843,8 +845,8 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
843 | desc->lld.mbr_cfg = chan_cc; | 845 | desc->lld.mbr_cfg = chan_cc; |
844 | 846 | ||
845 | dev_dbg(chan2dev(chan), | 847 | dev_dbg(chan2dev(chan), |
846 | "%s: lld: mbr_sa=0x%08x, mbr_da=0x%08x, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n", | 848 | "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n", |
847 | __func__, desc->lld.mbr_sa, desc->lld.mbr_da, desc->lld.mbr_ubc, desc->lld.mbr_cfg); | 849 | __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc, desc->lld.mbr_cfg); |
848 | 850 | ||
849 | /* Chain lld. */ | 851 | /* Chain lld. */ |
850 | if (prev) { | 852 | if (prev) { |
@@ -879,7 +881,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, | |||
879 | struct list_head *descs_list; | 881 | struct list_head *descs_list; |
880 | enum dma_status ret; | 882 | enum dma_status ret; |
881 | int residue; | 883 | int residue; |
882 | u32 cur_nda; | 884 | u32 cur_nda, mask, value; |
883 | u8 dwidth = at_xdmac_get_dwidth(atchan->cfg[AT_XDMAC_CUR_CFG]); | 885 | u8 dwidth = at_xdmac_get_dwidth(atchan->cfg[AT_XDMAC_CUR_CFG]); |
884 | 886 | ||
885 | ret = dma_cookie_status(chan, cookie, txstate); | 887 | ret = dma_cookie_status(chan, cookie, txstate); |
@@ -899,14 +901,22 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, | |||
899 | */ | 901 | */ |
900 | if (!desc->active_xfer) { | 902 | if (!desc->active_xfer) { |
901 | dma_set_residue(txstate, desc->xfer_size); | 903 | dma_set_residue(txstate, desc->xfer_size); |
904 | spin_unlock_bh(&atchan->lock); | ||
902 | return ret; | 905 | return ret; |
903 | } | 906 | } |
904 | 907 | ||
905 | residue = desc->xfer_size; | 908 | residue = desc->xfer_size; |
906 | /* Flush FIFO. */ | 909 | /* |
907 | at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask); | 910 | * Flush FIFO: only relevant when the transfer is source peripheral |
908 | while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS)) | 911 | * synchronized. |
909 | cpu_relax(); | 912 | */ |
913 | mask = AT_XDMAC_CC_TYPE | AT_XDMAC_CC_DSYNC; | ||
914 | value = AT_XDMAC_CC_TYPE_PER_TRAN | AT_XDMAC_CC_DSYNC_PER2MEM; | ||
915 | if ((atchan->cfg[AT_XDMAC_CUR_CFG] & mask) == value) { | ||
916 | at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask); | ||
917 | while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS)) | ||
918 | cpu_relax(); | ||
919 | } | ||
910 | 920 | ||
911 | cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc; | 921 | cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc; |
912 | /* | 922 | /* |
@@ -927,8 +937,8 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, | |||
927 | dma_set_residue(txstate, residue); | 937 | dma_set_residue(txstate, residue); |
928 | 938 | ||
929 | dev_dbg(chan2dev(chan), | 939 | dev_dbg(chan2dev(chan), |
930 | "%s: desc=0x%p, tx_dma_desc.phys=0x%08x, tx_status=%d, cookie=%d, residue=%d\n", | 940 | "%s: desc=0x%p, tx_dma_desc.phys=%pad, tx_status=%d, cookie=%d, residue=%d\n", |
931 | __func__, desc, desc->tx_dma_desc.phys, ret, cookie, residue); | 941 | __func__, desc, &desc->tx_dma_desc.phys, ret, cookie, residue); |
932 | 942 | ||
933 | return ret; | 943 | return ret; |
934 | } | 944 | } |
@@ -1384,6 +1394,11 @@ static int at_xdmac_probe(struct platform_device *pdev) | |||
1384 | dma_cap_set(DMA_CYCLIC, atxdmac->dma.cap_mask); | 1394 | dma_cap_set(DMA_CYCLIC, atxdmac->dma.cap_mask); |
1385 | dma_cap_set(DMA_MEMCPY, atxdmac->dma.cap_mask); | 1395 | dma_cap_set(DMA_MEMCPY, atxdmac->dma.cap_mask); |
1386 | dma_cap_set(DMA_SLAVE, atxdmac->dma.cap_mask); | 1396 | dma_cap_set(DMA_SLAVE, atxdmac->dma.cap_mask); |
1397 | /* | ||
1398 | * Without DMA_PRIVATE the driver is not able to allocate more than | ||
1399 | * one channel, second allocation fails in private_candidate. | ||
1400 | */ | ||
1401 | dma_cap_set(DMA_PRIVATE, atxdmac->dma.cap_mask); | ||
1387 | atxdmac->dma.dev = &pdev->dev; | 1402 | atxdmac->dma.dev = &pdev->dev; |
1388 | atxdmac->dma.device_alloc_chan_resources = at_xdmac_alloc_chan_resources; | 1403 | atxdmac->dma.device_alloc_chan_resources = at_xdmac_alloc_chan_resources; |
1389 | atxdmac->dma.device_free_chan_resources = at_xdmac_free_chan_resources; | 1404 | atxdmac->dma.device_free_chan_resources = at_xdmac_free_chan_resources; |
@@ -1393,7 +1408,6 @@ static int at_xdmac_probe(struct platform_device *pdev) | |||
1393 | atxdmac->dma.device_prep_dma_memcpy = at_xdmac_prep_dma_memcpy; | 1408 | atxdmac->dma.device_prep_dma_memcpy = at_xdmac_prep_dma_memcpy; |
1394 | atxdmac->dma.device_prep_slave_sg = at_xdmac_prep_slave_sg; | 1409 | atxdmac->dma.device_prep_slave_sg = at_xdmac_prep_slave_sg; |
1395 | atxdmac->dma.device_control = at_xdmac_control; | 1410 | atxdmac->dma.device_control = at_xdmac_control; |
1396 | atxdmac->dma.chancnt = nr_channels; | ||
1397 | atxdmac->dma.device_slave_caps = at_xdmac_device_slave_caps; | 1411 | atxdmac->dma.device_slave_caps = at_xdmac_device_slave_caps; |
1398 | 1412 | ||
1399 | /* Disable all chans and interrupts. */ | 1413 | /* Disable all chans and interrupts. */ |