Lines Matching refs:chan
151 struct axi_dmac_chan chan;
154 static struct axi_dmac *chan_to_axi_dmac(struct axi_dmac_chan *chan)
156 return container_of(chan->vchan.chan.device, struct axi_dmac,
162 return container_of(c, struct axi_dmac_chan, vchan.chan);
181 static int axi_dmac_src_is_mem(struct axi_dmac_chan *chan)
183 return chan->src_type == AXI_DMAC_BUS_TYPE_AXI_MM;
186 static int axi_dmac_dest_is_mem(struct axi_dmac_chan *chan)
188 return chan->dest_type == AXI_DMAC_BUS_TYPE_AXI_MM;
191 static bool axi_dmac_check_len(struct axi_dmac_chan *chan, unsigned int len)
195 if ((len & chan->length_align_mask) != 0) /* Not aligned */
200 static bool axi_dmac_check_addr(struct axi_dmac_chan *chan, dma_addr_t addr)
202 if ((addr & chan->address_align_mask) != 0) /* Not aligned */
207 static void axi_dmac_start_transfer(struct axi_dmac_chan *chan)
209 struct axi_dmac *dmac = chan_to_axi_dmac(chan);
220 desc = chan->next_desc;
223 vdesc = vchan_next_desc(&chan->vchan);
226 list_move_tail(&vdesc->node, &chan->active_descs);
243 chan->next_desc = NULL;
246 chan->next_desc = desc;
251 if (axi_dmac_dest_is_mem(chan)) {
256 if (axi_dmac_src_is_mem(chan)) {
266 if (chan->hw_cyclic && desc->cyclic && !desc->vdesc.tx.callback &&
270 if (chan->hw_partial_xfer)
279 static struct axi_dmac_desc *axi_dmac_active_desc(struct axi_dmac_chan *chan)
281 return list_first_entry_or_null(&chan->active_descs,
285 static inline unsigned int axi_dmac_total_sg_bytes(struct axi_dmac_chan *chan,
288 if (chan->hw_2d)
294 static void axi_dmac_dequeue_partial_xfers(struct axi_dmac_chan *chan)
296 struct axi_dmac *dmac = chan_to_axi_dmac(chan);
307 list_for_each_entry(desc, &chan->active_descs, vdesc.node) {
340 static void axi_dmac_compute_residue(struct axi_dmac_chan *chan,
357 total = axi_dmac_total_sg_bytes(chan, sg);
362 static bool axi_dmac_transfer_done(struct axi_dmac_chan *chan,
369 active = axi_dmac_active_desc(chan);
373 if (chan->hw_partial_xfer &&
375 axi_dmac_dequeue_partial_xfers(chan);
391 axi_dmac_compute_residue(chan, active);
403 active = axi_dmac_active_desc(chan);
423 spin_lock(&dmac->chan.vchan.lock);
429 start_next = axi_dmac_transfer_done(&dmac->chan, completed);
433 axi_dmac_start_transfer(&dmac->chan);
434 spin_unlock(&dmac->chan.vchan.lock);
441 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
442 struct axi_dmac *dmac = chan_to_axi_dmac(chan);
446 spin_lock_irqsave(&chan->vchan.lock, flags);
448 chan->next_desc = NULL;
449 vchan_get_all_descriptors(&chan->vchan, &head);
450 list_splice_tail_init(&chan->active_descs, &head);
451 spin_unlock_irqrestore(&chan->vchan.lock, flags);
453 vchan_dma_desc_free_list(&chan->vchan, &head);
460 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
462 vchan_synchronize(&chan->vchan);
467 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
468 struct axi_dmac *dmac = chan_to_axi_dmac(chan);
473 spin_lock_irqsave(&chan->vchan.lock, flags);
474 if (vchan_issue_pending(&chan->vchan))
475 axi_dmac_start_transfer(chan);
476 spin_unlock_irqrestore(&chan->vchan.lock, flags);
496 static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *chan,
506 num_segments = DIV_ROUND_UP(period_len, chan->max_length);
509 segment_size = ((segment_size - 1) | chan->length_align_mask) + 1;
544 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
551 if (direction != chan->direction)
556 num_sgs += DIV_ROUND_UP(sg_dma_len(sg), chan->max_length);
565 if (!axi_dmac_check_addr(chan, sg_dma_address(sg)) ||
566 !axi_dmac_check_len(chan, sg_dma_len(sg))) {
571 dsg = axi_dmac_fill_linear_sg(chan, direction, sg_dma_address(sg), 1,
577 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
585 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
589 if (direction != chan->direction)
592 if (!axi_dmac_check_len(chan, buf_len) ||
593 !axi_dmac_check_addr(chan, buf_addr))
600 num_segments = DIV_ROUND_UP(period_len, chan->max_length);
606 axi_dmac_fill_linear_sg(chan, direction, buf_addr, num_periods,
611 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
618 struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
625 if (xt->dir != chan->direction)
628 if (axi_dmac_src_is_mem(chan)) {
629 if (!xt->src_inc || !axi_dmac_check_addr(chan, xt->src_start))
633 if (axi_dmac_dest_is_mem(chan)) {
634 if (!xt->dst_inc || !axi_dmac_check_addr(chan, xt->dst_start))
641 if (chan->hw_2d) {
642 if (!axi_dmac_check_len(chan, xt->sgl[0].size) ||
645 if (xt->sgl[0].size + dst_icg > chan->max_length ||
646 xt->sgl[0].size + src_icg > chan->max_length)
651 if (chan->max_length / xt->sgl[0].size < xt->numf)
653 if (!axi_dmac_check_len(chan, xt->sgl[0].size * xt->numf))
661 if (axi_dmac_src_is_mem(chan)) {
666 if (axi_dmac_dest_is_mem(chan)) {
671 if (chan->hw_2d) {
682 return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
733 static void axi_dmac_adjust_chan_params(struct axi_dmac_chan *chan)
735 chan->address_align_mask = max(chan->dest_width, chan->src_width) - 1;
737 if (axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan))
738 chan->direction = DMA_MEM_TO_MEM;
739 else if (!axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan))
740 chan->direction = DMA_MEM_TO_DEV;
741 else if (axi_dmac_dest_is_mem(chan) && !axi_dmac_src_is_mem(chan))
742 chan->direction = DMA_DEV_TO_MEM;
744 chan->direction = DMA_DEV_TO_DEV;
753 struct axi_dmac_chan *chan)
771 chan->src_type = val;
778 chan->dest_type = val;
783 chan->src_width = val / 8;
788 chan->dest_width = val / 8;
790 axi_dmac_adjust_chan_params(chan);
805 ret = axi_dmac_parse_chan_dt(of_chan, &dmac->chan);
819 struct axi_dmac_chan *chan = &dmac->chan;
833 chan->src_type = val;
840 chan->dest_type = val;
848 chan->src_width = 1 << val;
855 chan->dest_width = 1 << val;
857 axi_dmac_adjust_chan_params(chan);
864 struct axi_dmac_chan *chan = &dmac->chan;
868 chan->hw_cyclic = true;
872 chan->hw_2d = true;
875 chan->max_length = axi_dmac_read(dmac, AXI_DMAC_REG_X_LENGTH);
876 if (chan->max_length != UINT_MAX)
877 chan->max_length++;
881 chan->dest_type == AXI_DMAC_BUS_TYPE_AXI_MM) {
889 chan->src_type == AXI_DMAC_BUS_TYPE_AXI_MM) {
896 chan->hw_partial_xfer = true;
900 chan->length_align_mask =
903 chan->length_align_mask = chan->address_align_mask;
949 INIT_LIST_HEAD(&dmac->chan.active_descs);
966 dma_dev->src_addr_widths = BIT(dmac->chan.src_width);
967 dma_dev->dst_addr_widths = BIT(dmac->chan.dest_width);
968 dma_dev->directions = BIT(dmac->chan.direction);
972 dmac->chan.vchan.desc_free = axi_dmac_desc_free;
973 vchan_init(&dmac->chan.vchan, dma_dev);
979 dma_dev->copy_align = (dmac->chan.address_align_mask + 1);
1038 tasklet_kill(&dmac->chan.vchan.task);