diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dma/at_hdmac.c | 208 | ||||
-rw-r--r-- | drivers/dma/at_hdmac_regs.h | 49 |
2 files changed, 214 insertions, 43 deletions
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 64dbf0ce128e..9a1e5fb412ed 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c | |||
@@ -608,6 +608,187 @@ err_desc_get: | |||
608 | return NULL; | 608 | return NULL; |
609 | } | 609 | } |
610 | 610 | ||
611 | |||
612 | /** | ||
613 | * atc_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction | ||
614 | * @chan: DMA channel | ||
615 | * @sgl: scatterlist to transfer to/from | ||
616 | * @sg_len: number of entries in @scatterlist | ||
617 | * @direction: DMA direction | ||
618 | * @flags: tx descriptor status flags | ||
619 | */ | ||
620 | static struct dma_async_tx_descriptor * | ||
621 | atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | ||
622 | unsigned int sg_len, enum dma_data_direction direction, | ||
623 | unsigned long flags) | ||
624 | { | ||
625 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | ||
626 | struct at_dma_slave *atslave = chan->private; | ||
627 | struct at_desc *first = NULL; | ||
628 | struct at_desc *prev = NULL; | ||
629 | u32 ctrla; | ||
630 | u32 ctrlb; | ||
631 | dma_addr_t reg; | ||
632 | unsigned int reg_width; | ||
633 | unsigned int mem_width; | ||
634 | unsigned int i; | ||
635 | struct scatterlist *sg; | ||
636 | size_t total_len = 0; | ||
637 | |||
638 | dev_vdbg(chan2dev(chan), "prep_slave_sg: %s f0x%lx\n", | ||
639 | direction == DMA_TO_DEVICE ? "TO DEVICE" : "FROM DEVICE", | ||
640 | flags); | ||
641 | |||
642 | if (unlikely(!atslave || !sg_len)) { | ||
643 | dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n"); | ||
644 | return NULL; | ||
645 | } | ||
646 | |||
647 | reg_width = atslave->reg_width; | ||
648 | |||
649 | sg_len = dma_map_sg(chan2parent(chan), sgl, sg_len, direction); | ||
650 | |||
651 | ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla; | ||
652 | ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN; | ||
653 | |||
654 | switch (direction) { | ||
655 | case DMA_TO_DEVICE: | ||
656 | ctrla |= ATC_DST_WIDTH(reg_width); | ||
657 | ctrlb |= ATC_DST_ADDR_MODE_FIXED | ||
658 | | ATC_SRC_ADDR_MODE_INCR | ||
659 | | ATC_FC_MEM2PER; | ||
660 | reg = atslave->tx_reg; | ||
661 | for_each_sg(sgl, sg, sg_len, i) { | ||
662 | struct at_desc *desc; | ||
663 | u32 len; | ||
664 | u32 mem; | ||
665 | |||
666 | desc = atc_desc_get(atchan); | ||
667 | if (!desc) | ||
668 | goto err_desc_get; | ||
669 | |||
670 | mem = sg_phys(sg); | ||
671 | len = sg_dma_len(sg); | ||
672 | mem_width = 2; | ||
673 | if (unlikely(mem & 3 || len & 3)) | ||
674 | mem_width = 0; | ||
675 | |||
676 | desc->lli.saddr = mem; | ||
677 | desc->lli.daddr = reg; | ||
678 | desc->lli.ctrla = ctrla | ||
679 | | ATC_SRC_WIDTH(mem_width) | ||
680 | | len >> mem_width; | ||
681 | desc->lli.ctrlb = ctrlb; | ||
682 | |||
683 | if (!first) { | ||
684 | first = desc; | ||
685 | } else { | ||
686 | /* inform the HW lli about chaining */ | ||
687 | prev->lli.dscr = desc->txd.phys; | ||
688 | /* insert the link descriptor to the LD ring */ | ||
689 | list_add_tail(&desc->desc_node, | ||
690 | &first->txd.tx_list); | ||
691 | } | ||
692 | prev = desc; | ||
693 | total_len += len; | ||
694 | } | ||
695 | break; | ||
696 | case DMA_FROM_DEVICE: | ||
697 | ctrla |= ATC_SRC_WIDTH(reg_width); | ||
698 | ctrlb |= ATC_DST_ADDR_MODE_INCR | ||
699 | | ATC_SRC_ADDR_MODE_FIXED | ||
700 | | ATC_FC_PER2MEM; | ||
701 | |||
702 | reg = atslave->rx_reg; | ||
703 | for_each_sg(sgl, sg, sg_len, i) { | ||
704 | struct at_desc *desc; | ||
705 | u32 len; | ||
706 | u32 mem; | ||
707 | |||
708 | desc = atc_desc_get(atchan); | ||
709 | if (!desc) | ||
710 | goto err_desc_get; | ||
711 | |||
712 | mem = sg_phys(sg); | ||
713 | len = sg_dma_len(sg); | ||
714 | mem_width = 2; | ||
715 | if (unlikely(mem & 3 || len & 3)) | ||
716 | mem_width = 0; | ||
717 | |||
718 | desc->lli.saddr = reg; | ||
719 | desc->lli.daddr = mem; | ||
720 | desc->lli.ctrla = ctrla | ||
721 | | ATC_DST_WIDTH(mem_width) | ||
722 | | len >> mem_width; | ||
723 | desc->lli.ctrlb = ctrlb; | ||
724 | |||
725 | if (!first) { | ||
726 | first = desc; | ||
727 | } else { | ||
728 | /* inform the HW lli about chaining */ | ||
729 | prev->lli.dscr = desc->txd.phys; | ||
730 | /* insert the link descriptor to the LD ring */ | ||
731 | list_add_tail(&desc->desc_node, | ||
732 | &first->txd.tx_list); | ||
733 | } | ||
734 | prev = desc; | ||
735 | total_len += len; | ||
736 | } | ||
737 | break; | ||
738 | default: | ||
739 | return NULL; | ||
740 | } | ||
741 | |||
742 | /* set end-of-link to the last link descriptor of list*/ | ||
743 | set_desc_eol(prev); | ||
744 | |||
745 | /* First descriptor of the chain embedds additional information */ | ||
746 | first->txd.cookie = -EBUSY; | ||
747 | first->len = total_len; | ||
748 | |||
749 | /* last link descriptor of list is responsible of flags */ | ||
750 | prev->txd.flags = flags; /* client is in control of this ack */ | ||
751 | |||
752 | return &first->txd; | ||
753 | |||
754 | err_desc_get: | ||
755 | dev_err(chan2dev(chan), "not enough descriptors available\n"); | ||
756 | atc_desc_put(atchan, first); | ||
757 | return NULL; | ||
758 | } | ||
759 | |||
760 | static void atc_terminate_all(struct dma_chan *chan) | ||
761 | { | ||
762 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | ||
763 | struct at_dma *atdma = to_at_dma(chan->device); | ||
764 | struct at_desc *desc, *_desc; | ||
765 | LIST_HEAD(list); | ||
766 | |||
767 | /* | ||
768 | * This is only called when something went wrong elsewhere, so | ||
769 | * we don't really care about the data. Just disable the | ||
770 | * channel. We still have to poll the channel enable bit due | ||
771 | * to AHB/HSB limitations. | ||
772 | */ | ||
773 | spin_lock_bh(&atchan->lock); | ||
774 | |||
775 | dma_writel(atdma, CHDR, atchan->mask); | ||
776 | |||
777 | /* confirm that this channel is disabled */ | ||
778 | while (dma_readl(atdma, CHSR) & atchan->mask) | ||
779 | cpu_relax(); | ||
780 | |||
781 | /* active_list entries will end up before queued entries */ | ||
782 | list_splice_init(&atchan->queue, &list); | ||
783 | list_splice_init(&atchan->active_list, &list); | ||
784 | |||
785 | spin_unlock_bh(&atchan->lock); | ||
786 | |||
787 | /* Flush all pending and queued descriptors */ | ||
788 | list_for_each_entry_safe(desc, _desc, &list, desc_node) | ||
789 | atc_chain_complete(atchan, desc); | ||
790 | } | ||
791 | |||
611 | /** | 792 | /** |
612 | * atc_is_tx_complete - poll for transaction completion | 793 | * atc_is_tx_complete - poll for transaction completion |
613 | * @chan: DMA channel | 794 | * @chan: DMA channel |
@@ -686,7 +867,9 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) | |||
686 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | 867 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
687 | struct at_dma *atdma = to_at_dma(chan->device); | 868 | struct at_dma *atdma = to_at_dma(chan->device); |
688 | struct at_desc *desc; | 869 | struct at_desc *desc; |
870 | struct at_dma_slave *atslave; | ||
689 | int i; | 871 | int i; |
872 | u32 cfg; | ||
690 | LIST_HEAD(tmp_list); | 873 | LIST_HEAD(tmp_list); |
691 | 874 | ||
692 | dev_vdbg(chan2dev(chan), "alloc_chan_resources\n"); | 875 | dev_vdbg(chan2dev(chan), "alloc_chan_resources\n"); |
@@ -697,7 +880,23 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) | |||
697 | return -EIO; | 880 | return -EIO; |
698 | } | 881 | } |
699 | 882 | ||
700 | /* have we already been set up? */ | 883 | cfg = ATC_DEFAULT_CFG; |
884 | |||
885 | atslave = chan->private; | ||
886 | if (atslave) { | ||
887 | /* | ||
888 | * We need controller-specific data to set up slave | ||
889 | * transfers. | ||
890 | */ | ||
891 | BUG_ON(!atslave->dma_dev || atslave->dma_dev != atdma->dma_common.dev); | ||
892 | |||
893 | /* if cfg configuration specified take it instad of default */ | ||
894 | if (atslave->cfg) | ||
895 | cfg = atslave->cfg; | ||
896 | } | ||
897 | |||
898 | /* have we already been set up? | ||
899 | * reconfigure channel but no need to reallocate descriptors */ | ||
701 | if (!list_empty(&atchan->free_list)) | 900 | if (!list_empty(&atchan->free_list)) |
702 | return atchan->descs_allocated; | 901 | return atchan->descs_allocated; |
703 | 902 | ||
@@ -719,7 +918,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) | |||
719 | spin_unlock_bh(&atchan->lock); | 918 | spin_unlock_bh(&atchan->lock); |
720 | 919 | ||
721 | /* channel parameters */ | 920 | /* channel parameters */ |
722 | channel_writel(atchan, CFG, ATC_DEFAULT_CFG); | 921 | channel_writel(atchan, CFG, cfg); |
723 | 922 | ||
724 | dev_dbg(chan2dev(chan), | 923 | dev_dbg(chan2dev(chan), |
725 | "alloc_chan_resources: allocated %d descriptors\n", | 924 | "alloc_chan_resources: allocated %d descriptors\n", |
@@ -888,6 +1087,11 @@ static int __init at_dma_probe(struct platform_device *pdev) | |||
888 | if (dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask)) | 1087 | if (dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask)) |
889 | atdma->dma_common.device_prep_dma_memcpy = atc_prep_dma_memcpy; | 1088 | atdma->dma_common.device_prep_dma_memcpy = atc_prep_dma_memcpy; |
890 | 1089 | ||
1090 | if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)) { | ||
1091 | atdma->dma_common.device_prep_slave_sg = atc_prep_slave_sg; | ||
1092 | atdma->dma_common.device_terminate_all = atc_terminate_all; | ||
1093 | } | ||
1094 | |||
891 | dma_writel(atdma, EN, AT_DMA_ENABLE); | 1095 | dma_writel(atdma, EN, AT_DMA_ENABLE); |
892 | 1096 | ||
893 | dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n", | 1097 | dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n", |
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index ad2d4f402bf7..4c972afc49ec 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h | |||
@@ -87,29 +87,14 @@ | |||
87 | /* Bitfields in CTRLA */ | 87 | /* Bitfields in CTRLA */ |
88 | #define ATC_BTSIZE_MAX 0xFFFFUL /* Maximum Buffer Transfer Size */ | 88 | #define ATC_BTSIZE_MAX 0xFFFFUL /* Maximum Buffer Transfer Size */ |
89 | #define ATC_BTSIZE(x) (ATC_BTSIZE_MAX & (x)) /* Buffer Transfer Size */ | 89 | #define ATC_BTSIZE(x) (ATC_BTSIZE_MAX & (x)) /* Buffer Transfer Size */ |
90 | #define ATC_SCSIZE_MASK (0x7 << 16) /* Source Chunk Transfer Size */ | 90 | /* Chunck Tranfer size definitions are in at_hdmac.h */ |
91 | #define ATC_SCSIZE_1 (0x0 << 16) | ||
92 | #define ATC_SCSIZE_4 (0x1 << 16) | ||
93 | #define ATC_SCSIZE_8 (0x2 << 16) | ||
94 | #define ATC_SCSIZE_16 (0x3 << 16) | ||
95 | #define ATC_SCSIZE_32 (0x4 << 16) | ||
96 | #define ATC_SCSIZE_64 (0x5 << 16) | ||
97 | #define ATC_SCSIZE_128 (0x6 << 16) | ||
98 | #define ATC_SCSIZE_256 (0x7 << 16) | ||
99 | #define ATC_DCSIZE_MASK (0x7 << 20) /* Destination Chunk Transfer Size */ | ||
100 | #define ATC_DCSIZE_1 (0x0 << 20) | ||
101 | #define ATC_DCSIZE_4 (0x1 << 20) | ||
102 | #define ATC_DCSIZE_8 (0x2 << 20) | ||
103 | #define ATC_DCSIZE_16 (0x3 << 20) | ||
104 | #define ATC_DCSIZE_32 (0x4 << 20) | ||
105 | #define ATC_DCSIZE_64 (0x5 << 20) | ||
106 | #define ATC_DCSIZE_128 (0x6 << 20) | ||
107 | #define ATC_DCSIZE_256 (0x7 << 20) | ||
108 | #define ATC_SRC_WIDTH_MASK (0x3 << 24) /* Source Single Transfer Size */ | 91 | #define ATC_SRC_WIDTH_MASK (0x3 << 24) /* Source Single Transfer Size */ |
92 | #define ATC_SRC_WIDTH(x) ((x) << 24) | ||
109 | #define ATC_SRC_WIDTH_BYTE (0x0 << 24) | 93 | #define ATC_SRC_WIDTH_BYTE (0x0 << 24) |
110 | #define ATC_SRC_WIDTH_HALFWORD (0x1 << 24) | 94 | #define ATC_SRC_WIDTH_HALFWORD (0x1 << 24) |
111 | #define ATC_SRC_WIDTH_WORD (0x2 << 24) | 95 | #define ATC_SRC_WIDTH_WORD (0x2 << 24) |
112 | #define ATC_DST_WIDTH_MASK (0x3 << 28) /* Destination Single Transfer Size */ | 96 | #define ATC_DST_WIDTH_MASK (0x3 << 28) /* Destination Single Transfer Size */ |
97 | #define ATC_DST_WIDTH(x) ((x) << 28) | ||
113 | #define ATC_DST_WIDTH_BYTE (0x0 << 28) | 98 | #define ATC_DST_WIDTH_BYTE (0x0 << 28) |
114 | #define ATC_DST_WIDTH_HALFWORD (0x1 << 28) | 99 | #define ATC_DST_WIDTH_HALFWORD (0x1 << 28) |
115 | #define ATC_DST_WIDTH_WORD (0x2 << 28) | 100 | #define ATC_DST_WIDTH_WORD (0x2 << 28) |
@@ -129,7 +114,8 @@ | |||
129 | #define ATC_FC_PER2PER (0x3 << 21) /* Periph-to-Periph (DMA) */ | 114 | #define ATC_FC_PER2PER (0x3 << 21) /* Periph-to-Periph (DMA) */ |
130 | #define ATC_FC_PER2MEM_PER (0x4 << 21) /* Periph-to-Mem (Peripheral) */ | 115 | #define ATC_FC_PER2MEM_PER (0x4 << 21) /* Periph-to-Mem (Peripheral) */ |
131 | #define ATC_FC_MEM2PER_PER (0x5 << 21) /* Mem-to-Periph (Peripheral) */ | 116 | #define ATC_FC_MEM2PER_PER (0x5 << 21) /* Mem-to-Periph (Peripheral) */ |
132 | #define ATC_FC_PER2PER_PER (0x6 << 21) /* Periph-to-Periph (Src Peripheral) */ | 117 | #define ATC_FC_PER2PER_SRCPER (0x6 << 21) /* Periph-to-Periph (Src Peripheral) */ |
118 | #define ATC_FC_PER2PER_DSTPER (0x7 << 21) /* Periph-to-Periph (Dst Peripheral) */ | ||
133 | #define ATC_SRC_ADDR_MODE_MASK (0x3 << 24) | 119 | #define ATC_SRC_ADDR_MODE_MASK (0x3 << 24) |
134 | #define ATC_SRC_ADDR_MODE_INCR (0x0 << 24) /* Incrementing Mode */ | 120 | #define ATC_SRC_ADDR_MODE_INCR (0x0 << 24) /* Incrementing Mode */ |
135 | #define ATC_SRC_ADDR_MODE_DECR (0x1 << 24) /* Decrementing Mode */ | 121 | #define ATC_SRC_ADDR_MODE_DECR (0x1 << 24) /* Decrementing Mode */ |
@@ -142,27 +128,7 @@ | |||
142 | #define ATC_AUTO (0x1 << 31) /* Auto multiple buffer tx enable */ | 128 | #define ATC_AUTO (0x1 << 31) /* Auto multiple buffer tx enable */ |
143 | 129 | ||
144 | /* Bitfields in CFG */ | 130 | /* Bitfields in CFG */ |
145 | #define ATC_SRC_PER(h) (0xFU & (h)) /* Channel src rq associated with periph handshaking ifc h */ | 131 | /* are in at_hdmac.h */ |
146 | #define ATC_DST_PER(h) ((0xFU & (h)) << 4) /* Channel dst rq associated with periph handshaking ifc h */ | ||
147 | #define ATC_SRC_REP (0x1 << 8) /* Source Replay Mod */ | ||
148 | #define ATC_SRC_H2SEL (0x1 << 9) /* Source Handshaking Mod */ | ||
149 | #define ATC_SRC_H2SEL_SW (0x0 << 9) | ||
150 | #define ATC_SRC_H2SEL_HW (0x1 << 9) | ||
151 | #define ATC_DST_REP (0x1 << 12) /* Destination Replay Mod */ | ||
152 | #define ATC_DST_H2SEL (0x1 << 13) /* Destination Handshaking Mod */ | ||
153 | #define ATC_DST_H2SEL_SW (0x0 << 13) | ||
154 | #define ATC_DST_H2SEL_HW (0x1 << 13) | ||
155 | #define ATC_SOD (0x1 << 16) /* Stop On Done */ | ||
156 | #define ATC_LOCK_IF (0x1 << 20) /* Interface Lock */ | ||
157 | #define ATC_LOCK_B (0x1 << 21) /* AHB Bus Lock */ | ||
158 | #define ATC_LOCK_IF_L (0x1 << 22) /* Master Interface Arbiter Lock */ | ||
159 | #define ATC_LOCK_IF_L_CHUNK (0x0 << 22) | ||
160 | #define ATC_LOCK_IF_L_BUFFER (0x1 << 22) | ||
161 | #define ATC_AHB_PROT_MASK (0x7 << 24) /* AHB Protection */ | ||
162 | #define ATC_FIFOCFG_MASK (0x3 << 28) /* FIFO Request Configuration */ | ||
163 | #define ATC_FIFOCFG_LARGESTBURST (0x0 << 28) | ||
164 | #define ATC_FIFOCFG_HALFFIFO (0x1 << 28) | ||
165 | #define ATC_FIFOCFG_ENOUGHSPACE (0x2 << 28) | ||
166 | 132 | ||
167 | /* Bitfields in SPIP */ | 133 | /* Bitfields in SPIP */ |
168 | #define ATC_SPIP_HOLE(x) (0xFFFFU & (x)) | 134 | #define ATC_SPIP_HOLE(x) (0xFFFFU & (x)) |
@@ -316,11 +282,12 @@ static void vdbg_dump_regs(struct at_dma_chan *atchan) | |||
316 | dma_readl(atdma, CHSR)); | 282 | dma_readl(atdma, CHSR)); |
317 | 283 | ||
318 | dev_err(chan2dev(&atchan->chan_common), | 284 | dev_err(chan2dev(&atchan->chan_common), |
319 | " channel: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n", | 285 | " channel: s0x%x d0x%x ctrl0x%x:0x%x cfg0x%x l0x%x\n", |
320 | channel_readl(atchan, SADDR), | 286 | channel_readl(atchan, SADDR), |
321 | channel_readl(atchan, DADDR), | 287 | channel_readl(atchan, DADDR), |
322 | channel_readl(atchan, CTRLA), | 288 | channel_readl(atchan, CTRLA), |
323 | channel_readl(atchan, CTRLB), | 289 | channel_readl(atchan, CTRLB), |
290 | channel_readl(atchan, CFG), | ||
324 | channel_readl(atchan, DSCR)); | 291 | channel_readl(atchan, DSCR)); |
325 | } | 292 | } |
326 | #else | 293 | #else |