Lines Matching refs:chan

147 	struct axi_dmac_chan chan;
150 static struct axi_dmac *chan_to_axi_dmac(struct axi_dmac_chan *chan)
152 return container_of(chan->vchan.chan.device, struct axi_dmac,
158 return container_of(c, struct axi_dmac_chan, vchan.chan);
177 static int axi_dmac_src_is_mem(struct axi_dmac_chan *chan)
179 return chan->src_type == AXI_DMAC_BUS_TYPE_AXI_MM;
182 static int axi_dmac_dest_is_mem(struct axi_dmac_chan *chan)
184 return chan->dest_type == AXI_DMAC_BUS_TYPE_AXI_MM;
187 static bool axi_dmac_check_len(struct axi_dmac_chan *chan, unsigned int len)
191 if ((len & chan->length_align_mask) != 0) /* Not aligned */
196 static bool axi_dmac_check_addr(struct axi_dmac_chan *chan, dma_addr_t addr)
198 if ((addr & chan->address_align_mask) != 0) /* Not aligned */
203 static void axi_dmac_start_transfer(struct axi_dmac_chan *chan)
205 struct axi_dmac *dmac = chan_to_axi_dmac(chan);
216 desc = chan->next_desc;
219 vdesc = vchan_next_desc(&chan->vchan);
222 list_move_tail(&vdesc->node, &chan->active_descs);
239 chan->next_desc = NULL;
242 chan->next_desc = desc;
247 if (axi_dmac_dest_is_mem(chan)) {
252 if (axi_dmac_src_is_mem(chan)) {
262 if (chan->hw_cyclic && desc->cyclic && !desc->vdesc.tx.callback &&
266 if (chan->hw_partial_xfer)
275 static struct axi_dmac_desc *axi_dmac_active_desc(struct axi_dmac_chan *chan)
277 return list_first_entry_or_null(&chan->active_descs,
281 static inline unsigned int axi_dmac_total_sg_bytes(struct axi_dmac_chan *chan,
284 if (chan->hw_2d)
290 static void axi_dmac_dequeue_partial_xfers(struct axi_dmac_chan *chan)
292 struct axi_dmac *dmac = chan_to_axi_dmac(chan);
303 list_for_each_entry(desc, &chan->active_descs, vdesc.node) {
336 static void axi_dmac_compute_residue(struct axi_dmac_chan *chan,
353 total = axi_dmac_total_sg_bytes(chan, sg);
358 static bool axi_dmac_transfer_done(struct axi_dmac_chan *chan,
365 active = axi_dmac_active_desc(chan);
369 if (chan->hw_partial_xfer &&
371 axi_dmac_dequeue_partial_xfers(chan);
387 axi_dmac_compute_residue(chan, active);
399 active = axi_dmac_active_desc(chan);
419 spin_lock(&dmac->chan.vchan.lock);
425 start_next = axi_dmac_transfer_done(&dmac->chan, completed);
429 axi_dmac_start_transfer(&dmac->chan);
430 spin_unlock(&dmac->chan.vchan.lock);
437 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
438 struct axi_dmac *dmac = chan_to_axi_dmac(chan);
442 spin_lock_irqsave(&chan->vchan.lock, flags);
444 chan->next_desc = NULL;
445 vchan_get_all_descriptors(&chan->vchan, &head);
446 list_splice_tail_init(&chan->active_descs, &head);
447 spin_unlock_irqrestore(&chan->vchan.lock, flags);
449 vchan_dma_desc_free_list(&chan->vchan, &head);
456 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
458 vchan_synchronize(&chan->vchan);
463 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
464 struct axi_dmac *dmac = chan_to_axi_dmac(chan);
469 spin_lock_irqsave(&chan->vchan.lock, flags);
470 if (vchan_issue_pending(&chan->vchan))
471 axi_dmac_start_transfer(chan);
472 spin_unlock_irqrestore(&chan->vchan.lock, flags);
492 static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *chan,
502 num_segments = DIV_ROUND_UP(period_len, chan->max_length);
505 segment_size = ((segment_size - 1) | chan->length_align_mask) + 1;
540 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
547 if (direction != chan->direction)
552 num_sgs += DIV_ROUND_UP(sg_dma_len(sg), chan->max_length);
561 if (!axi_dmac_check_addr(chan, sg_dma_address(sg)) ||
562 !axi_dmac_check_len(chan, sg_dma_len(sg))) {
567 dsg = axi_dmac_fill_linear_sg(chan, direction, sg_dma_address(sg), 1,
573 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
581 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
585 if (direction != chan->direction)
588 if (!axi_dmac_check_len(chan, buf_len) ||
589 !axi_dmac_check_addr(chan, buf_addr))
596 num_segments = DIV_ROUND_UP(period_len, chan->max_length);
602 axi_dmac_fill_linear_sg(chan, direction, buf_addr, num_periods,
607 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
614 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
621 if (xt->dir != chan->direction)
624 if (axi_dmac_src_is_mem(chan)) {
625 if (!xt->src_inc || !axi_dmac_check_addr(chan, xt->src_start))
629 if (axi_dmac_dest_is_mem(chan)) {
630 if (!xt->dst_inc || !axi_dmac_check_addr(chan, xt->dst_start))
637 if (chan->hw_2d) {
638 if (!axi_dmac_check_len(chan, xt->sgl[0].size) ||
641 if (xt->sgl[0].size + dst_icg > chan->max_length ||
642 xt->sgl[0].size + src_icg > chan->max_length)
647 if (chan->max_length / xt->sgl[0].size < xt->numf)
649 if (!axi_dmac_check_len(chan, xt->sgl[0].size * xt->numf))
657 if (axi_dmac_src_is_mem(chan)) {
662 if (axi_dmac_dest_is_mem(chan)) {
667 if (chan->hw_2d) {
678 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
729 static void axi_dmac_adjust_chan_params(struct axi_dmac_chan *chan)
731 chan->address_align_mask = max(chan->dest_width, chan->src_width) - 1;
733 if (axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan))
734 chan->direction = DMA_MEM_TO_MEM;
735 else if (!axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan))
736 chan->direction = DMA_MEM_TO_DEV;
737 else if (axi_dmac_dest_is_mem(chan) && !axi_dmac_src_is_mem(chan))
738 chan->direction = DMA_DEV_TO_MEM;
740 chan->direction = DMA_DEV_TO_DEV;
749 struct axi_dmac_chan *chan)
767 chan->src_type = val;
774 chan->dest_type = val;
779 chan->src_width = val / 8;
784 chan->dest_width = val / 8;
786 axi_dmac_adjust_chan_params(chan);
801 ret = axi_dmac_parse_chan_dt(of_chan, &dmac->chan);
815 struct axi_dmac_chan *chan = &dmac->chan;
829 chan->src_type = val;
836 chan->dest_type = val;
844 chan->src_width = 1 << val;
851 chan->dest_width = 1 << val;
853 axi_dmac_adjust_chan_params(chan);
860 struct axi_dmac_chan *chan = &dmac->chan;
864 chan->hw_cyclic = true;
868 chan->hw_2d = true;
871 chan->max_length = axi_dmac_read(dmac, AXI_DMAC_REG_X_LENGTH);
872 if (chan->max_length != UINT_MAX)
873 chan->max_length++;
877 chan->dest_type == AXI_DMAC_BUS_TYPE_AXI_MM) {
885 chan->src_type == AXI_DMAC_BUS_TYPE_AXI_MM) {
892 chan->hw_partial_xfer = true;
896 chan->length_align_mask =
899 chan->length_align_mask = chan->address_align_mask;
947 INIT_LIST_HEAD(&dmac->chan.active_descs);
965 dma_dev->src_addr_widths = BIT(dmac->chan.src_width);
966 dma_dev->dst_addr_widths = BIT(dmac->chan.dest_width);
967 dma_dev->directions = BIT(dmac->chan.direction);
971 dmac->chan.vchan.desc_free = axi_dmac_desc_free;
972 vchan_init(&dmac->chan.vchan, dma_dev);
978 dma_dev->copy_align = (dmac->chan.address_align_mask + 1);
1025 tasklet_kill(&dmac->chan.vchan.task);