Lines Matching +full:dw +full:- +full:pcie
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
17 #include <linux/dma-mapping.h>
19 #include "dw-edma-core.h"
20 #include "dw-edma-v0-core.h"
22 #include "../virt-dma.h"
27 return &dchan->dev->device; in dchan2dev()
33 return &chan->vc.chan.dev->device; in chan2dev()
50 INIT_LIST_HEAD(&burst->list); in dw_edma_alloc_burst()
51 if (chunk->burst) { in dw_edma_alloc_burst()
53 chunk->bursts_alloc++; in dw_edma_alloc_burst()
54 list_add_tail(&burst->list, &chunk->burst->list); in dw_edma_alloc_burst()
57 chunk->bursts_alloc = 0; in dw_edma_alloc_burst()
58 chunk->burst = burst; in dw_edma_alloc_burst()
66 struct dw_edma_chip *chip = desc->chan->dw->chip; in dw_edma_alloc_chunk()
67 struct dw_edma_chan *chan = desc->chan; in dw_edma_alloc_chunk()
74 INIT_LIST_HEAD(&chunk->list); in dw_edma_alloc_chunk()
75 chunk->chan = chan; in dw_edma_alloc_chunk()
79 * - Odd chunks originate CB equal to 0 in dw_edma_alloc_chunk()
80 * - Even chunks originate CB equal to 1 in dw_edma_alloc_chunk()
82 chunk->cb = !(desc->chunks_alloc % 2); in dw_edma_alloc_chunk()
83 if (chan->dir == EDMA_DIR_WRITE) { in dw_edma_alloc_chunk()
84 chunk->ll_region.paddr = chip->ll_region_wr[chan->id].paddr; in dw_edma_alloc_chunk()
85 chunk->ll_region.vaddr = chip->ll_region_wr[chan->id].vaddr; in dw_edma_alloc_chunk()
87 chunk->ll_region.paddr = chip->ll_region_rd[chan->id].paddr; in dw_edma_alloc_chunk()
88 chunk->ll_region.vaddr = chip->ll_region_rd[chan->id].vaddr; in dw_edma_alloc_chunk()
91 if (desc->chunk) { in dw_edma_alloc_chunk()
97 desc->chunks_alloc++; in dw_edma_alloc_chunk()
98 list_add_tail(&chunk->list, &desc->chunk->list); in dw_edma_alloc_chunk()
101 chunk->burst = NULL; in dw_edma_alloc_chunk()
102 desc->chunks_alloc = 0; in dw_edma_alloc_chunk()
103 desc->chunk = chunk; in dw_edma_alloc_chunk()
117 desc->chan = chan; in dw_edma_alloc_desc()
131 list_for_each_entry_safe(child, _next, &chunk->burst->list, list) { in dw_edma_free_burst()
132 list_del(&child->list); in dw_edma_free_burst()
134 chunk->bursts_alloc--; in dw_edma_free_burst()
139 chunk->burst = NULL; in dw_edma_free_burst()
146 if (!desc->chunk) in dw_edma_free_chunk()
150 list_for_each_entry_safe(child, _next, &desc->chunk->list, list) { in dw_edma_free_chunk()
152 list_del(&child->list); in dw_edma_free_chunk()
154 desc->chunks_alloc--; in dw_edma_free_chunk()
159 desc->chunk = NULL; in dw_edma_free_chunk()
179 vd = vchan_next_desc(&chan->vc); in dw_edma_start_transfer()
187 child = list_first_entry_or_null(&desc->chunk->list, in dw_edma_start_transfer()
192 dw_edma_v0_core_start(child, !desc->xfer_sz); in dw_edma_start_transfer()
193 desc->xfer_sz += child->ll_region.sz; in dw_edma_start_transfer()
195 list_del(&child->list); in dw_edma_start_transfer()
197 desc->chunks_alloc--; in dw_edma_start_transfer()
205 memcpy(&chan->config, config, sizeof(*config)); in dw_edma_device_config()
206 chan->configured = true; in dw_edma_device_config()
216 if (!chan->configured) in dw_edma_device_pause()
217 err = -EPERM; in dw_edma_device_pause()
218 else if (chan->status != EDMA_ST_BUSY) in dw_edma_device_pause()
219 err = -EPERM; in dw_edma_device_pause()
220 else if (chan->request != EDMA_REQ_NONE) in dw_edma_device_pause()
221 err = -EPERM; in dw_edma_device_pause()
223 chan->request = EDMA_REQ_PAUSE; in dw_edma_device_pause()
233 if (!chan->configured) { in dw_edma_device_resume()
234 err = -EPERM; in dw_edma_device_resume()
235 } else if (chan->status != EDMA_ST_PAUSE) { in dw_edma_device_resume()
236 err = -EPERM; in dw_edma_device_resume()
237 } else if (chan->request != EDMA_REQ_NONE) { in dw_edma_device_resume()
238 err = -EPERM; in dw_edma_device_resume()
240 chan->status = EDMA_ST_BUSY; in dw_edma_device_resume()
252 if (!chan->configured) { in dw_edma_device_terminate_all()
254 } else if (chan->status == EDMA_ST_PAUSE) { in dw_edma_device_terminate_all()
255 chan->status = EDMA_ST_IDLE; in dw_edma_device_terminate_all()
256 chan->configured = false; in dw_edma_device_terminate_all()
257 } else if (chan->status == EDMA_ST_IDLE) { in dw_edma_device_terminate_all()
258 chan->configured = false; in dw_edma_device_terminate_all()
264 chan->status = EDMA_ST_IDLE; in dw_edma_device_terminate_all()
265 chan->configured = false; in dw_edma_device_terminate_all()
266 } else if (chan->request > EDMA_REQ_PAUSE) { in dw_edma_device_terminate_all()
267 err = -EPERM; in dw_edma_device_terminate_all()
269 chan->request = EDMA_REQ_STOP; in dw_edma_device_terminate_all()
280 spin_lock_irqsave(&chan->vc.lock, flags); in dw_edma_device_issue_pending()
281 if (chan->configured && chan->request == EDMA_REQ_NONE && in dw_edma_device_issue_pending()
282 chan->status == EDMA_ST_IDLE && vchan_issue_pending(&chan->vc)) { in dw_edma_device_issue_pending()
283 chan->status = EDMA_ST_BUSY; in dw_edma_device_issue_pending()
286 spin_unlock_irqrestore(&chan->vc.lock, flags); in dw_edma_device_issue_pending()
304 if (ret == DMA_IN_PROGRESS && chan->status == EDMA_ST_PAUSE) in dw_edma_device_tx_status()
310 spin_lock_irqsave(&chan->vc.lock, flags); in dw_edma_device_tx_status()
311 vd = vchan_find_desc(&chan->vc, cookie); in dw_edma_device_tx_status()
315 residue = desc->alloc_sz - desc->xfer_sz; in dw_edma_device_tx_status()
317 spin_unlock_irqrestore(&chan->vc.lock, flags); in dw_edma_device_tx_status()
328 struct dw_edma_chan *chan = dchan2dw_edma_chan(xfer->dchan); in dw_edma_device_transfer()
329 enum dma_transfer_direction dir = xfer->direction; in dw_edma_device_transfer()
338 if (!chan->configured) in dw_edma_device_transfer()
342 * Local Root Port/End-point Remote End-point in dw_edma_device_transfer()
343 * +-----------------------+ PCIe bus +----------------------+ in dw_edma_device_transfer()
344 * | | +-+ | | in dw_edma_device_transfer()
345 * | DEV_TO_MEM Rx Ch <----+ +---+ Tx Ch DEV_TO_MEM | in dw_edma_device_transfer()
347 * | MEM_TO_DEV Tx Ch +----+ +---> Rx Ch MEM_TO_DEV | in dw_edma_device_transfer()
348 * | | +-+ | | in dw_edma_device_transfer()
349 * +-----------------------+ +----------------------+ in dw_edma_device_transfer()
352 * If eDMA is embedded into the DW PCIe RP/EP and controlled from the in dw_edma_device_transfer()
355 * (EDMA_DIR_WRITE) - for the write operations (MEM_TO_DEV). in dw_edma_device_transfer()
358 * If eDMA is embedded into a Remote PCIe EP and is controlled by the in dw_edma_device_transfer()
359 * MWr/MRd TLPs sent from the CPU's PCIe host controller, the Tx in dw_edma_device_transfer()
361 * (DEV_TO_MEM) and the Rx channel (EDMA_DIR_READ) - for the write in dw_edma_device_transfer()
367 if (chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) { in dw_edma_device_transfer()
368 if ((chan->dir == EDMA_DIR_READ && dir != DMA_DEV_TO_MEM) || in dw_edma_device_transfer()
369 (chan->dir == EDMA_DIR_WRITE && dir != DMA_MEM_TO_DEV)) in dw_edma_device_transfer()
372 if ((chan->dir == EDMA_DIR_WRITE && dir != DMA_DEV_TO_MEM) || in dw_edma_device_transfer()
373 (chan->dir == EDMA_DIR_READ && dir != DMA_MEM_TO_DEV)) in dw_edma_device_transfer()
377 if (xfer->type == EDMA_XFER_CYCLIC) { in dw_edma_device_transfer()
378 if (!xfer->xfer.cyclic.len || !xfer->xfer.cyclic.cnt) in dw_edma_device_transfer()
380 } else if (xfer->type == EDMA_XFER_SCATTER_GATHER) { in dw_edma_device_transfer()
381 if (xfer->xfer.sg.len < 1) in dw_edma_device_transfer()
383 } else if (xfer->type == EDMA_XFER_INTERLEAVED) { in dw_edma_device_transfer()
384 if (!xfer->xfer.il->numf) in dw_edma_device_transfer()
386 if (xfer->xfer.il->numf > 0 && xfer->xfer.il->frame_size > 0) in dw_edma_device_transfer()
400 if (xfer->type == EDMA_XFER_INTERLEAVED) { in dw_edma_device_transfer()
401 src_addr = xfer->xfer.il->src_start; in dw_edma_device_transfer()
402 dst_addr = xfer->xfer.il->dst_start; in dw_edma_device_transfer()
404 src_addr = chan->config.src_addr; in dw_edma_device_transfer()
405 dst_addr = chan->config.dst_addr; in dw_edma_device_transfer()
408 if (xfer->type == EDMA_XFER_CYCLIC) { in dw_edma_device_transfer()
409 cnt = xfer->xfer.cyclic.cnt; in dw_edma_device_transfer()
410 } else if (xfer->type == EDMA_XFER_SCATTER_GATHER) { in dw_edma_device_transfer()
411 cnt = xfer->xfer.sg.len; in dw_edma_device_transfer()
412 sg = xfer->xfer.sg.sgl; in dw_edma_device_transfer()
413 } else if (xfer->type == EDMA_XFER_INTERLEAVED) { in dw_edma_device_transfer()
414 if (xfer->xfer.il->numf > 0) in dw_edma_device_transfer()
415 cnt = xfer->xfer.il->numf; in dw_edma_device_transfer()
417 cnt = xfer->xfer.il->frame_size; in dw_edma_device_transfer()
421 if (xfer->type == EDMA_XFER_SCATTER_GATHER && !sg) in dw_edma_device_transfer()
424 if (chunk->bursts_alloc == chan->ll_max) { in dw_edma_device_transfer()
434 if (xfer->type == EDMA_XFER_CYCLIC) in dw_edma_device_transfer()
435 burst->sz = xfer->xfer.cyclic.len; in dw_edma_device_transfer()
436 else if (xfer->type == EDMA_XFER_SCATTER_GATHER) in dw_edma_device_transfer()
437 burst->sz = sg_dma_len(sg); in dw_edma_device_transfer()
438 else if (xfer->type == EDMA_XFER_INTERLEAVED) in dw_edma_device_transfer()
439 burst->sz = xfer->xfer.il->sgl[i].size; in dw_edma_device_transfer()
441 chunk->ll_region.sz += burst->sz; in dw_edma_device_transfer()
442 desc->alloc_sz += burst->sz; in dw_edma_device_transfer()
445 burst->sar = src_addr; in dw_edma_device_transfer()
446 if (xfer->type == EDMA_XFER_CYCLIC) { in dw_edma_device_transfer()
447 burst->dar = xfer->xfer.cyclic.paddr; in dw_edma_device_transfer()
448 } else if (xfer->type == EDMA_XFER_SCATTER_GATHER) { in dw_edma_device_transfer()
450 burst->dar = sg_dma_address(sg); in dw_edma_device_transfer()
460 burst->dar = dst_addr; in dw_edma_device_transfer()
461 if (xfer->type == EDMA_XFER_CYCLIC) { in dw_edma_device_transfer()
462 burst->sar = xfer->xfer.cyclic.paddr; in dw_edma_device_transfer()
463 } else if (xfer->type == EDMA_XFER_SCATTER_GATHER) { in dw_edma_device_transfer()
465 burst->sar = sg_dma_address(sg); in dw_edma_device_transfer()
476 if (xfer->type == EDMA_XFER_SCATTER_GATHER) { in dw_edma_device_transfer()
478 } else if (xfer->type == EDMA_XFER_INTERLEAVED && in dw_edma_device_transfer()
479 xfer->xfer.il->frame_size > 0) { in dw_edma_device_transfer()
480 struct dma_interleaved_template *il = xfer->xfer.il; in dw_edma_device_transfer()
481 struct data_chunk *dc = &il->sgl[i]; in dw_edma_device_transfer()
483 if (il->src_sgl) { in dw_edma_device_transfer()
484 src_addr += burst->sz; in dw_edma_device_transfer()
488 if (il->dst_sgl) { in dw_edma_device_transfer()
489 dst_addr += burst->sz; in dw_edma_device_transfer()
495 return vchan_tx_prep(&chan->vc, &desc->vd, xfer->flags); in dw_edma_device_transfer()
549 xfer.direction = ilt->dir; in dw_edma_device_prep_interleaved_dma()
565 spin_lock_irqsave(&chan->vc.lock, flags); in dw_edma_done_interrupt()
566 vd = vchan_next_desc(&chan->vc); in dw_edma_done_interrupt()
568 switch (chan->request) { in dw_edma_done_interrupt()
571 if (desc->chunks_alloc) { in dw_edma_done_interrupt()
572 chan->status = EDMA_ST_BUSY; in dw_edma_done_interrupt()
575 list_del(&vd->node); in dw_edma_done_interrupt()
577 chan->status = EDMA_ST_IDLE; in dw_edma_done_interrupt()
582 list_del(&vd->node); in dw_edma_done_interrupt()
584 chan->request = EDMA_REQ_NONE; in dw_edma_done_interrupt()
585 chan->status = EDMA_ST_IDLE; in dw_edma_done_interrupt()
589 chan->request = EDMA_REQ_NONE; in dw_edma_done_interrupt()
590 chan->status = EDMA_ST_PAUSE; in dw_edma_done_interrupt()
597 spin_unlock_irqrestore(&chan->vc.lock, flags); in dw_edma_done_interrupt()
607 spin_lock_irqsave(&chan->vc.lock, flags); in dw_edma_abort_interrupt()
608 vd = vchan_next_desc(&chan->vc); in dw_edma_abort_interrupt()
610 list_del(&vd->node); in dw_edma_abort_interrupt()
613 spin_unlock_irqrestore(&chan->vc.lock, flags); in dw_edma_abort_interrupt()
614 chan->request = EDMA_REQ_NONE; in dw_edma_abort_interrupt()
615 chan->status = EDMA_ST_IDLE; in dw_edma_abort_interrupt()
621 struct dw_edma *dw = dw_irq->dw; in dw_edma_interrupt() local
627 total = dw->wr_ch_cnt; in dw_edma_interrupt()
629 mask = dw_irq->wr_mask; in dw_edma_interrupt()
631 total = dw->rd_ch_cnt; in dw_edma_interrupt()
632 off = dw->wr_ch_cnt; in dw_edma_interrupt()
633 mask = dw_irq->rd_mask; in dw_edma_interrupt()
636 val = dw_edma_v0_core_status_done_int(dw, write ? in dw_edma_interrupt()
641 struct dw_edma_chan *chan = &dw->chan[pos + off]; in dw_edma_interrupt()
646 val = dw_edma_v0_core_status_abort_int(dw, write ? in dw_edma_interrupt()
651 struct dw_edma_chan *chan = &dw->chan[pos + off]; in dw_edma_interrupt()
681 if (chan->status != EDMA_ST_IDLE) in dw_edma_alloc_chan_resources()
682 return -EBUSY; in dw_edma_alloc_chan_resources()
704 static int dw_edma_channel_setup(struct dw_edma *dw, bool write, in dw_edma_channel_setup() argument
707 struct dw_edma_chip *chip = dw->chip; in dw_edma_channel_setup()
709 struct device *dev = chip->dev; in dw_edma_channel_setup()
720 cnt = dw->wr_ch_cnt; in dw_edma_channel_setup()
721 dma = &dw->wr_edma; in dw_edma_channel_setup()
725 i = dw->wr_ch_cnt; in dw_edma_channel_setup()
726 cnt = dw->rd_ch_cnt; in dw_edma_channel_setup()
727 dma = &dw->rd_edma; in dw_edma_channel_setup()
732 INIT_LIST_HEAD(&dma->channels); in dw_edma_channel_setup()
733 for (j = 0; (alloc || dw->nr_irqs == 1) && j < cnt; j++, i++) { in dw_edma_channel_setup()
734 chan = &dw->chan[i]; in dw_edma_channel_setup()
738 return -ENOMEM; in dw_edma_channel_setup()
740 chan->vc.chan.private = dt_region; in dw_edma_channel_setup()
742 chan->dw = dw; in dw_edma_channel_setup()
743 chan->id = j; in dw_edma_channel_setup()
744 chan->dir = write ? EDMA_DIR_WRITE : EDMA_DIR_READ; in dw_edma_channel_setup()
745 chan->configured = false; in dw_edma_channel_setup()
746 chan->request = EDMA_REQ_NONE; in dw_edma_channel_setup()
747 chan->status = EDMA_ST_IDLE; in dw_edma_channel_setup()
750 chan->ll_max = (chip->ll_region_wr[j].sz / EDMA_LL_SZ); in dw_edma_channel_setup()
752 chan->ll_max = (chip->ll_region_rd[j].sz / EDMA_LL_SZ); in dw_edma_channel_setup()
753 chan->ll_max -= 1; in dw_edma_channel_setup()
756 write ? "write" : "read", j, chan->ll_max); in dw_edma_channel_setup()
758 if (dw->nr_irqs == 1) in dw_edma_channel_setup()
763 irq = &dw->irq[pos]; in dw_edma_channel_setup()
766 irq->wr_mask |= BIT(j); in dw_edma_channel_setup()
768 irq->rd_mask |= BIT(j); in dw_edma_channel_setup()
770 irq->dw = dw; in dw_edma_channel_setup()
771 memcpy(&chan->msi, &irq->msi, sizeof(chan->msi)); in dw_edma_channel_setup()
775 chan->msi.address_hi, chan->msi.address_lo, in dw_edma_channel_setup()
776 chan->msi.data); in dw_edma_channel_setup()
778 chan->vc.desc_free = vchan_free_desc; in dw_edma_channel_setup()
779 vchan_init(&chan->vc, dma); in dw_edma_channel_setup()
782 dt_region->paddr = chip->dt_region_wr[j].paddr; in dw_edma_channel_setup()
783 dt_region->vaddr = chip->dt_region_wr[j].vaddr; in dw_edma_channel_setup()
784 dt_region->sz = chip->dt_region_wr[j].sz; in dw_edma_channel_setup()
786 dt_region->paddr = chip->dt_region_rd[j].paddr; in dw_edma_channel_setup()
787 dt_region->vaddr = chip->dt_region_rd[j].vaddr; in dw_edma_channel_setup()
788 dt_region->sz = chip->dt_region_rd[j].sz; in dw_edma_channel_setup()
795 dma_cap_zero(dma->cap_mask); in dw_edma_channel_setup()
796 dma_cap_set(DMA_SLAVE, dma->cap_mask); in dw_edma_channel_setup()
797 dma_cap_set(DMA_CYCLIC, dma->cap_mask); in dw_edma_channel_setup()
798 dma_cap_set(DMA_PRIVATE, dma->cap_mask); in dw_edma_channel_setup()
799 dma_cap_set(DMA_INTERLEAVE, dma->cap_mask); in dw_edma_channel_setup()
800 dma->directions = BIT(write ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV); in dw_edma_channel_setup()
801 dma->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); in dw_edma_channel_setup()
802 dma->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); in dw_edma_channel_setup()
803 dma->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR; in dw_edma_channel_setup()
804 dma->chancnt = cnt; in dw_edma_channel_setup()
807 dma->dev = chip->dev; in dw_edma_channel_setup()
808 dma->device_alloc_chan_resources = dw_edma_alloc_chan_resources; in dw_edma_channel_setup()
809 dma->device_free_chan_resources = dw_edma_free_chan_resources; in dw_edma_channel_setup()
810 dma->device_config = dw_edma_device_config; in dw_edma_channel_setup()
811 dma->device_pause = dw_edma_device_pause; in dw_edma_channel_setup()
812 dma->device_resume = dw_edma_device_resume; in dw_edma_channel_setup()
813 dma->device_terminate_all = dw_edma_device_terminate_all; in dw_edma_channel_setup()
814 dma->device_issue_pending = dw_edma_device_issue_pending; in dw_edma_channel_setup()
815 dma->device_tx_status = dw_edma_device_tx_status; in dw_edma_channel_setup()
816 dma->device_prep_slave_sg = dw_edma_device_prep_slave_sg; in dw_edma_channel_setup()
817 dma->device_prep_dma_cyclic = dw_edma_device_prep_dma_cyclic; in dw_edma_channel_setup()
818 dma->device_prep_interleaved_dma = dw_edma_device_prep_interleaved_dma; in dw_edma_channel_setup()
820 dma_set_max_seg_size(dma->dev, U32_MAX); in dw_edma_channel_setup()
832 (*nr_irqs)--; in dw_edma_dec_irq_alloc()
842 static int dw_edma_irq_request(struct dw_edma *dw, in dw_edma_irq_request() argument
845 struct dw_edma_chip *chip = dw->chip; in dw_edma_irq_request()
846 struct device *dev = dw->chip->dev; in dw_edma_irq_request()
853 ch_cnt = dw->wr_ch_cnt + dw->rd_ch_cnt; in dw_edma_irq_request()
855 if (chip->nr_irqs < 1 || !chip->ops->irq_vector) in dw_edma_irq_request()
856 return -EINVAL; in dw_edma_irq_request()
858 dw->irq = devm_kcalloc(dev, chip->nr_irqs, sizeof(*dw->irq), GFP_KERNEL); in dw_edma_irq_request()
859 if (!dw->irq) in dw_edma_irq_request()
860 return -ENOMEM; in dw_edma_irq_request()
862 if (chip->nr_irqs == 1) { in dw_edma_irq_request()
864 irq = chip->ops->irq_vector(dev, 0); in dw_edma_irq_request()
866 IRQF_SHARED, dw->name, &dw->irq[0]); in dw_edma_irq_request()
868 dw->nr_irqs = 0; in dw_edma_irq_request()
873 get_cached_msi_msg(irq, &dw->irq[0].msi); in dw_edma_irq_request()
875 dw->nr_irqs = 1; in dw_edma_irq_request()
878 int tmp = chip->nr_irqs; in dw_edma_irq_request()
881 dw_edma_dec_irq_alloc(&tmp, wr_alloc, dw->wr_ch_cnt); in dw_edma_irq_request()
882 dw_edma_dec_irq_alloc(&tmp, rd_alloc, dw->rd_ch_cnt); in dw_edma_irq_request()
885 dw_edma_add_irq_mask(&wr_mask, *wr_alloc, dw->wr_ch_cnt); in dw_edma_irq_request()
886 dw_edma_add_irq_mask(&rd_mask, *rd_alloc, dw->rd_ch_cnt); in dw_edma_irq_request()
889 irq = chip->ops->irq_vector(dev, i); in dw_edma_irq_request()
894 IRQF_SHARED, dw->name, in dw_edma_irq_request()
895 &dw->irq[i]); in dw_edma_irq_request()
897 dw->nr_irqs = i; in dw_edma_irq_request()
902 get_cached_msi_msg(irq, &dw->irq[i].msi); in dw_edma_irq_request()
905 dw->nr_irqs = i; in dw_edma_irq_request()
914 struct dw_edma *dw; in dw_edma_probe() local
920 return -EINVAL; in dw_edma_probe()
922 dev = chip->dev; in dw_edma_probe()
923 if (!dev || !chip->ops) in dw_edma_probe()
924 return -EINVAL; in dw_edma_probe()
926 dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL); in dw_edma_probe()
927 if (!dw) in dw_edma_probe()
928 return -ENOMEM; in dw_edma_probe()
930 dw->chip = chip; in dw_edma_probe()
932 raw_spin_lock_init(&dw->lock); in dw_edma_probe()
934 dw->wr_ch_cnt = min_t(u16, chip->ll_wr_cnt, in dw_edma_probe()
935 dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE)); in dw_edma_probe()
936 dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH); in dw_edma_probe()
938 dw->rd_ch_cnt = min_t(u16, chip->ll_rd_cnt, in dw_edma_probe()
939 dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ)); in dw_edma_probe()
940 dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH); in dw_edma_probe()
942 if (!dw->wr_ch_cnt && !dw->rd_ch_cnt) in dw_edma_probe()
943 return -EINVAL; in dw_edma_probe()
946 dw->wr_ch_cnt, dw->rd_ch_cnt); in dw_edma_probe()
949 dw->chan = devm_kcalloc(dev, dw->wr_ch_cnt + dw->rd_ch_cnt, in dw_edma_probe()
950 sizeof(*dw->chan), GFP_KERNEL); in dw_edma_probe()
951 if (!dw->chan) in dw_edma_probe()
952 return -ENOMEM; in dw_edma_probe()
954 snprintf(dw->name, sizeof(dw->name), "dw-edma-core:%d", chip->id); in dw_edma_probe()
957 dw_edma_v0_core_off(dw); in dw_edma_probe()
960 err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc); in dw_edma_probe()
965 err = dw_edma_channel_setup(dw, true, wr_alloc, rd_alloc); in dw_edma_probe()
970 err = dw_edma_channel_setup(dw, false, wr_alloc, rd_alloc); in dw_edma_probe()
975 dw_edma_v0_core_debugfs_on(dw); in dw_edma_probe()
977 chip->dw = dw; in dw_edma_probe()
982 for (i = (dw->nr_irqs - 1); i >= 0; i--) in dw_edma_probe()
983 free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]); in dw_edma_probe()
992 struct device *dev = chip->dev; in dw_edma_remove()
993 struct dw_edma *dw = chip->dw; in dw_edma_remove() local
997 dw_edma_v0_core_off(dw); in dw_edma_remove()
1000 for (i = (dw->nr_irqs - 1); i >= 0; i--) in dw_edma_remove()
1001 free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]); in dw_edma_remove()
1004 dma_async_device_unregister(&dw->wr_edma); in dw_edma_remove()
1005 list_for_each_entry_safe(chan, _chan, &dw->wr_edma.channels, in dw_edma_remove()
1007 tasklet_kill(&chan->vc.task); in dw_edma_remove()
1008 list_del(&chan->vc.chan.device_node); in dw_edma_remove()
1011 dma_async_device_unregister(&dw->rd_edma); in dw_edma_remove()
1012 list_for_each_entry_safe(chan, _chan, &dw->rd_edma.channels, in dw_edma_remove()
1014 tasklet_kill(&chan->vc.task); in dw_edma_remove()
1015 list_del(&chan->vc.chan.device_node); in dw_edma_remove()
1019 dw_edma_v0_core_debugfs_off(dw); in dw_edma_remove()