Lines Matching +full:slave +full:- +full:addr

1 // SPDX-License-Identifier: GPL-2.0-only
6 * Derived in part from arch/arm/mach-sa1100/dma.c,
20 #include "virt-dma.h"
68 u32 addr; member
89 /* protected by c->vc.lock */
93 /* protected by d->lock */
107 /* Protected by c->vc.lock */
118 struct dma_device slave; member
133 return container_of(dmadev, struct sa11x0_dma_dev, slave); in to_sa11x0_dma()
138 struct virt_dma_desc *vd = vchan_next_desc(&c->vc); in sa11x0_dma_next_desc()
150 list_del(&txd->vd.node); in sa11x0_dma_start_desc()
151 p->txd_load = txd; in sa11x0_dma_start_desc()
152 p->sg_load = 0; in sa11x0_dma_start_desc()
154 dev_vdbg(p->dev->slave.dev, "pchan %u: txd %p[%x]: starting: DDAR:%x\n", in sa11x0_dma_start_desc()
155 p->num, &txd->vd, txd->vd.tx.cookie, txd->ddar); in sa11x0_dma_start_desc()
161 struct sa11x0_dma_desc *txd = p->txd_load; in sa11x0_dma_start_sg()
163 void __iomem *base = p->base; in sa11x0_dma_start_sg()
176 if (p->sg_load == txd->sglen) { in sa11x0_dma_start_sg()
177 if (!txd->cyclic) { in sa11x0_dma_start_sg()
185 if (txn && txn->ddar == txd->ddar) { in sa11x0_dma_start_sg()
189 p->txd_load = NULL; in sa11x0_dma_start_sg()
194 p->sg_load = 0; in sa11x0_dma_start_sg()
198 sg = &txd->sg[p->sg_load++]; in sa11x0_dma_start_sg()
212 writel_relaxed(sg->addr, base + dbsx); in sa11x0_dma_start_sg()
213 writel_relaxed(sg->len, base + dbtx); in sa11x0_dma_start_sg()
216 dev_dbg(p->dev->slave.dev, "pchan %u: load: DCSR:%02x DBS%c:%08x DBT%c:%08x\n", in sa11x0_dma_start_sg()
217 p->num, dcsr, in sa11x0_dma_start_sg()
218 'A' + (dbsx == DMA_DBSB), sg->addr, in sa11x0_dma_start_sg()
219 'A' + (dbtx == DMA_DBTB), sg->len); in sa11x0_dma_start_sg()
225 struct sa11x0_dma_desc *txd = p->txd_done; in sa11x0_dma_complete()
227 if (++p->sg_done == txd->sglen) { in sa11x0_dma_complete()
228 if (!txd->cyclic) { in sa11x0_dma_complete()
229 vchan_cookie_complete(&txd->vd); in sa11x0_dma_complete()
231 p->sg_done = 0; in sa11x0_dma_complete()
232 p->txd_done = p->txd_load; in sa11x0_dma_complete()
234 if (!p->txd_done) in sa11x0_dma_complete()
235 tasklet_schedule(&p->dev->task); in sa11x0_dma_complete()
237 if ((p->sg_done % txd->period) == 0) in sa11x0_dma_complete()
238 vchan_cyclic_callback(&txd->vd); in sa11x0_dma_complete()
241 p->sg_done = 0; in sa11x0_dma_complete()
251 struct sa11x0_dma_dev *d = p->dev; in sa11x0_dma_irq()
255 dcsr = readl_relaxed(p->base + DMA_DCSR_R); in sa11x0_dma_irq()
261 p->base + DMA_DCSR_C); in sa11x0_dma_irq()
263 dev_dbg(d->slave.dev, "pchan %u: irq: DCSR:%02x\n", p->num, dcsr); in sa11x0_dma_irq()
266 …dev_err(d->slave.dev, "pchan %u: error. DCSR:%02x DDAR:%08x DBSA:%08x DBTA:%08x DBSB:%08x DBTB:%08… in sa11x0_dma_irq()
267 p->num, dcsr, in sa11x0_dma_irq()
268 readl_relaxed(p->base + DMA_DDAR), in sa11x0_dma_irq()
269 readl_relaxed(p->base + DMA_DBSA), in sa11x0_dma_irq()
270 readl_relaxed(p->base + DMA_DBTA), in sa11x0_dma_irq()
271 readl_relaxed(p->base + DMA_DBSB), in sa11x0_dma_irq()
272 readl_relaxed(p->base + DMA_DBTB)); in sa11x0_dma_irq()
275 c = p->vchan; in sa11x0_dma_irq()
279 spin_lock_irqsave(&c->vc.lock, flags); in sa11x0_dma_irq()
284 * change p->vchan or c->phy while the channel is actively in sa11x0_dma_irq()
287 if (c->phy == p) { in sa11x0_dma_irq()
293 spin_unlock_irqrestore(&c->vc.lock, flags); in sa11x0_dma_irq()
305 struct sa11x0_dma_phy *p = c->phy; in sa11x0_dma_start_txd()
308 p->txd_done = txd; in sa11x0_dma_start_txd()
309 p->sg_done = 0; in sa11x0_dma_start_txd()
312 WARN_ON(readl_relaxed(p->base + DMA_DCSR_R) & in sa11x0_dma_start_txd()
317 p->base + DMA_DCSR_C); in sa11x0_dma_start_txd()
318 writel_relaxed(txd->ddar, p->base + DMA_DDAR); in sa11x0_dma_start_txd()
333 dev_dbg(d->slave.dev, "tasklet enter\n"); in sa11x0_dma_tasklet()
335 list_for_each_entry(c, &d->slave.channels, vc.chan.device_node) { in sa11x0_dma_tasklet()
336 spin_lock_irq(&c->vc.lock); in sa11x0_dma_tasklet()
337 p = c->phy; in sa11x0_dma_tasklet()
338 if (p && !p->txd_done) { in sa11x0_dma_tasklet()
340 if (!p->txd_done) { in sa11x0_dma_tasklet()
342 dev_dbg(d->slave.dev, "pchan %u: free\n", p->num); in sa11x0_dma_tasklet()
345 c->phy = NULL; in sa11x0_dma_tasklet()
346 p->vchan = NULL; in sa11x0_dma_tasklet()
349 spin_unlock_irq(&c->vc.lock); in sa11x0_dma_tasklet()
352 spin_lock_irq(&d->lock); in sa11x0_dma_tasklet()
354 p = &d->phy[pch]; in sa11x0_dma_tasklet()
356 if (p->vchan == NULL && !list_empty(&d->chan_pending)) { in sa11x0_dma_tasklet()
357 c = list_first_entry(&d->chan_pending, in sa11x0_dma_tasklet()
359 list_del_init(&c->node); in sa11x0_dma_tasklet()
364 p->vchan = c; in sa11x0_dma_tasklet()
366 dev_dbg(d->slave.dev, "pchan %u: alloc vchan %p\n", pch, &c->vc); in sa11x0_dma_tasklet()
369 spin_unlock_irq(&d->lock); in sa11x0_dma_tasklet()
373 p = &d->phy[pch]; in sa11x0_dma_tasklet()
374 c = p->vchan; in sa11x0_dma_tasklet()
376 spin_lock_irq(&c->vc.lock); in sa11x0_dma_tasklet()
377 c->phy = p; in sa11x0_dma_tasklet()
380 spin_unlock_irq(&c->vc.lock); in sa11x0_dma_tasklet()
384 dev_dbg(d->slave.dev, "tasklet exit\n"); in sa11x0_dma_tasklet()
391 struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device); in sa11x0_dma_free_chan_resources()
394 spin_lock_irqsave(&d->lock, flags); in sa11x0_dma_free_chan_resources()
395 list_del_init(&c->node); in sa11x0_dma_free_chan_resources()
396 spin_unlock_irqrestore(&d->lock, flags); in sa11x0_dma_free_chan_resources()
398 vchan_free_chan_resources(&c->vc); in sa11x0_dma_free_chan_resources()
406 dcsr = readl_relaxed(p->base + DMA_DCSR_R); in sa11x0_dma_pos()
414 return readl_relaxed(p->base + reg); in sa11x0_dma_pos()
421 struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device); in sa11x0_dma_tx_status()
427 ret = dma_cookie_status(&c->vc.chan, cookie, state); in sa11x0_dma_tx_status()
432 return c->status; in sa11x0_dma_tx_status()
434 spin_lock_irqsave(&c->vc.lock, flags); in sa11x0_dma_tx_status()
435 p = c->phy; in sa11x0_dma_tx_status()
441 vd = vchan_find_desc(&c->vc, cookie); in sa11x0_dma_tx_status()
443 state->residue = container_of(vd, struct sa11x0_dma_desc, vd)->size; in sa11x0_dma_tx_status()
445 state->residue = 0; in sa11x0_dma_tx_status()
450 if (p->txd_done && p->txd_done->vd.tx.cookie == cookie) in sa11x0_dma_tx_status()
451 txd = p->txd_done; in sa11x0_dma_tx_status()
452 else if (p->txd_load && p->txd_load->vd.tx.cookie == cookie) in sa11x0_dma_tx_status()
453 txd = p->txd_load; in sa11x0_dma_tx_status()
457 ret = c->status; in sa11x0_dma_tx_status()
459 dma_addr_t addr = sa11x0_dma_pos(p); in sa11x0_dma_tx_status() local
462 dev_vdbg(d->slave.dev, "tx_status: addr:%pad\n", &addr); in sa11x0_dma_tx_status()
464 for (i = 0; i < txd->sglen; i++) { in sa11x0_dma_tx_status()
465 dev_vdbg(d->slave.dev, "tx_status: [%u] %x+%x\n", in sa11x0_dma_tx_status()
466 i, txd->sg[i].addr, txd->sg[i].len); in sa11x0_dma_tx_status()
467 if (addr >= txd->sg[i].addr && in sa11x0_dma_tx_status()
468 addr < txd->sg[i].addr + txd->sg[i].len) { in sa11x0_dma_tx_status()
471 len = txd->sg[i].len - in sa11x0_dma_tx_status()
472 (addr - txd->sg[i].addr); in sa11x0_dma_tx_status()
473 dev_vdbg(d->slave.dev, "tx_status: [%u] +%x\n", in sa11x0_dma_tx_status()
480 for (; i < txd->sglen; i++) { in sa11x0_dma_tx_status()
481 dev_vdbg(d->slave.dev, "tx_status: [%u] %x+%x ++\n", in sa11x0_dma_tx_status()
482 i, txd->sg[i].addr, txd->sg[i].len); in sa11x0_dma_tx_status()
483 bytes += txd->sg[i].len; in sa11x0_dma_tx_status()
486 state->residue = bytes; in sa11x0_dma_tx_status()
488 spin_unlock_irqrestore(&c->vc.lock, flags); in sa11x0_dma_tx_status()
490 dev_vdbg(d->slave.dev, "tx_status: bytes 0x%x\n", state->residue); in sa11x0_dma_tx_status()
496 * Move pending txds to the issued list, and re-init pending list.
503 struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device); in sa11x0_dma_issue_pending()
506 spin_lock_irqsave(&c->vc.lock, flags); in sa11x0_dma_issue_pending()
507 if (vchan_issue_pending(&c->vc)) { in sa11x0_dma_issue_pending()
508 if (!c->phy) { in sa11x0_dma_issue_pending()
509 spin_lock(&d->lock); in sa11x0_dma_issue_pending()
510 if (list_empty(&c->node)) { in sa11x0_dma_issue_pending()
511 list_add_tail(&c->node, &d->chan_pending); in sa11x0_dma_issue_pending()
512 tasklet_schedule(&d->task); in sa11x0_dma_issue_pending()
513 dev_dbg(d->slave.dev, "vchan %p: issued\n", &c->vc); in sa11x0_dma_issue_pending()
515 spin_unlock(&d->lock); in sa11x0_dma_issue_pending()
518 dev_dbg(d->slave.dev, "vchan %p: nothing to issue\n", &c->vc); in sa11x0_dma_issue_pending()
519 spin_unlock_irqrestore(&c->vc.lock, flags); in sa11x0_dma_issue_pending()
533 if (dir != (c->ddar & DDAR_RW ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV)) { in sa11x0_dma_prep_slave_sg()
534 dev_err(chan->device->dev, "vchan %p: bad DMA direction: DDAR:%08x dir:%u\n", in sa11x0_dma_prep_slave_sg()
535 &c->vc, c->ddar, dir); in sa11x0_dma_prep_slave_sg()
539 /* Do not allow zero-sized txds */ in sa11x0_dma_prep_slave_sg()
544 dma_addr_t addr = sg_dma_address(sgent); in sa11x0_dma_prep_slave_sg() local
548 j += DIV_ROUND_UP(len, DMA_MAX_SIZE & ~DMA_ALIGN) - 1; in sa11x0_dma_prep_slave_sg()
549 if (addr & DMA_ALIGN) { in sa11x0_dma_prep_slave_sg()
550 dev_dbg(chan->device->dev, "vchan %p: bad buffer alignment: %pad\n", in sa11x0_dma_prep_slave_sg()
551 &c->vc, &addr); in sa11x0_dma_prep_slave_sg()
558 dev_dbg(chan->device->dev, "vchan %p: kzalloc failed\n", &c->vc); in sa11x0_dma_prep_slave_sg()
561 txd->sglen = j; in sa11x0_dma_prep_slave_sg()
565 dma_addr_t addr = sg_dma_address(sgent); in sa11x0_dma_prep_slave_sg() local
576 * equal chunks - but make sure that we preserve the in sa11x0_dma_prep_slave_sg()
586 txd->sg[j].addr = addr; in sa11x0_dma_prep_slave_sg()
587 txd->sg[j].len = tlen; in sa11x0_dma_prep_slave_sg()
589 addr += tlen; in sa11x0_dma_prep_slave_sg()
590 len -= tlen; in sa11x0_dma_prep_slave_sg()
595 txd->ddar = c->ddar; in sa11x0_dma_prep_slave_sg()
596 txd->size = size; in sa11x0_dma_prep_slave_sg()
598 dev_dbg(chan->device->dev, "vchan %p: txd %p: size %zu nr %u\n", in sa11x0_dma_prep_slave_sg()
599 &c->vc, &txd->vd, txd->size, txd->sglen); in sa11x0_dma_prep_slave_sg()
601 return vchan_tx_prep(&c->vc, &txd->vd, flags); in sa11x0_dma_prep_slave_sg()
605 struct dma_chan *chan, dma_addr_t addr, size_t size, size_t period, in sa11x0_dma_prep_dma_cyclic() argument
613 if (dir != (c->ddar & DDAR_RW ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV)) { in sa11x0_dma_prep_dma_cyclic()
614 dev_err(chan->device->dev, "vchan %p: bad DMA direction: DDAR:%08x dir:%u\n", in sa11x0_dma_prep_dma_cyclic()
615 &c->vc, c->ddar, dir); in sa11x0_dma_prep_dma_cyclic()
622 /* Do not allow zero-sized txds */ in sa11x0_dma_prep_dma_cyclic()
628 dev_dbg(chan->device->dev, "vchan %p: kzalloc failed\n", &c->vc); in sa11x0_dma_prep_dma_cyclic()
631 txd->sglen = sglen; in sa11x0_dma_prep_dma_cyclic()
644 txd->sg[k].addr = addr; in sa11x0_dma_prep_dma_cyclic()
645 txd->sg[k].len = tlen; in sa11x0_dma_prep_dma_cyclic()
646 addr += tlen; in sa11x0_dma_prep_dma_cyclic()
647 len -= tlen; in sa11x0_dma_prep_dma_cyclic()
655 txd->ddar = c->ddar; in sa11x0_dma_prep_dma_cyclic()
656 txd->size = size; in sa11x0_dma_prep_dma_cyclic()
657 txd->cyclic = 1; in sa11x0_dma_prep_dma_cyclic()
658 txd->period = sgperiod; in sa11x0_dma_prep_dma_cyclic()
660 return vchan_tx_prep(&c->vc, &txd->vd, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); in sa11x0_dma_prep_dma_cyclic()
667 u32 ddar = c->ddar & ((0xf << 4) | DDAR_RW); in sa11x0_dma_device_config()
668 dma_addr_t addr; in sa11x0_dma_device_config() local
673 addr = cfg->src_addr; in sa11x0_dma_device_config()
674 width = cfg->src_addr_width; in sa11x0_dma_device_config()
675 maxburst = cfg->src_maxburst; in sa11x0_dma_device_config()
677 addr = cfg->dst_addr; in sa11x0_dma_device_config()
678 width = cfg->dst_addr_width; in sa11x0_dma_device_config()
679 maxburst = cfg->dst_maxburst; in sa11x0_dma_device_config()
685 return -EINVAL; in sa11x0_dma_device_config()
692 dev_dbg(c->vc.chan.device->dev, "vchan %p: dma_slave_config addr %pad width %u burst %u\n", in sa11x0_dma_device_config()
693 &c->vc, &addr, width, maxburst); in sa11x0_dma_device_config()
695 c->ddar = ddar | (addr & 0xf0000000) | (addr & 0x003ffffc) << 6; in sa11x0_dma_device_config()
703 struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device); in sa11x0_dma_device_pause()
707 dev_dbg(d->slave.dev, "vchan %p: pause\n", &c->vc); in sa11x0_dma_device_pause()
708 spin_lock_irqsave(&c->vc.lock, flags); in sa11x0_dma_device_pause()
709 if (c->status == DMA_IN_PROGRESS) { in sa11x0_dma_device_pause()
710 c->status = DMA_PAUSED; in sa11x0_dma_device_pause()
712 p = c->phy; in sa11x0_dma_device_pause()
714 writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_C); in sa11x0_dma_device_pause()
716 spin_lock(&d->lock); in sa11x0_dma_device_pause()
717 list_del_init(&c->node); in sa11x0_dma_device_pause()
718 spin_unlock(&d->lock); in sa11x0_dma_device_pause()
721 spin_unlock_irqrestore(&c->vc.lock, flags); in sa11x0_dma_device_pause()
729 struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device); in sa11x0_dma_device_resume()
733 dev_dbg(d->slave.dev, "vchan %p: resume\n", &c->vc); in sa11x0_dma_device_resume()
734 spin_lock_irqsave(&c->vc.lock, flags); in sa11x0_dma_device_resume()
735 if (c->status == DMA_PAUSED) { in sa11x0_dma_device_resume()
736 c->status = DMA_IN_PROGRESS; in sa11x0_dma_device_resume()
738 p = c->phy; in sa11x0_dma_device_resume()
740 writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_S); in sa11x0_dma_device_resume()
741 } else if (!list_empty(&c->vc.desc_issued)) { in sa11x0_dma_device_resume()
742 spin_lock(&d->lock); in sa11x0_dma_device_resume()
743 list_add_tail(&c->node, &d->chan_pending); in sa11x0_dma_device_resume()
744 spin_unlock(&d->lock); in sa11x0_dma_device_resume()
747 spin_unlock_irqrestore(&c->vc.lock, flags); in sa11x0_dma_device_resume()
755 struct sa11x0_dma_dev *d = to_sa11x0_dma(chan->device); in sa11x0_dma_device_terminate_all()
760 dev_dbg(d->slave.dev, "vchan %p: terminate all\n", &c->vc); in sa11x0_dma_device_terminate_all()
762 spin_lock_irqsave(&c->vc.lock, flags); in sa11x0_dma_device_terminate_all()
763 vchan_get_all_descriptors(&c->vc, &head); in sa11x0_dma_device_terminate_all()
765 p = c->phy; in sa11x0_dma_device_terminate_all()
767 dev_dbg(d->slave.dev, "pchan %u: terminating\n", p->num); in sa11x0_dma_device_terminate_all()
768 /* vchan is assigned to a pchan - stop the channel */ in sa11x0_dma_device_terminate_all()
772 p->base + DMA_DCSR_C); in sa11x0_dma_device_terminate_all()
774 if (p->txd_load) { in sa11x0_dma_device_terminate_all()
775 if (p->txd_load != p->txd_done) in sa11x0_dma_device_terminate_all()
776 list_add_tail(&p->txd_load->vd.node, &head); in sa11x0_dma_device_terminate_all()
777 p->txd_load = NULL; in sa11x0_dma_device_terminate_all()
779 if (p->txd_done) { in sa11x0_dma_device_terminate_all()
780 list_add_tail(&p->txd_done->vd.node, &head); in sa11x0_dma_device_terminate_all()
781 p->txd_done = NULL; in sa11x0_dma_device_terminate_all()
783 c->phy = NULL; in sa11x0_dma_device_terminate_all()
784 spin_lock(&d->lock); in sa11x0_dma_device_terminate_all()
785 p->vchan = NULL; in sa11x0_dma_device_terminate_all()
786 spin_unlock(&d->lock); in sa11x0_dma_device_terminate_all()
787 tasklet_schedule(&d->task); in sa11x0_dma_device_terminate_all()
789 spin_unlock_irqrestore(&c->vc.lock, flags); in sa11x0_dma_device_terminate_all()
790 vchan_dma_desc_free_list(&c->vc, &head); in sa11x0_dma_device_terminate_all()
821 { "sa11x0-ir", "tx", "Ser2ICPTr" },
822 { "sa11x0-ir", "rx", "Ser2ICPRc" },
823 { "sa11x0-ssp", "tx", "Ser4SSPTr" },
824 { "sa11x0-ssp", "rx", "Ser4SSPRc" },
832 return !strcmp(c->name, p); in sa11x0_dma_filter_fn()
840 INIT_LIST_HEAD(&dmadev->channels); in sa11x0_dma_init_dmadev()
841 dmadev->dev = dev; in sa11x0_dma_init_dmadev()
842 dmadev->device_free_chan_resources = sa11x0_dma_free_chan_resources; in sa11x0_dma_init_dmadev()
843 dmadev->device_config = sa11x0_dma_device_config; in sa11x0_dma_init_dmadev()
844 dmadev->device_pause = sa11x0_dma_device_pause; in sa11x0_dma_init_dmadev()
845 dmadev->device_resume = sa11x0_dma_device_resume; in sa11x0_dma_init_dmadev()
846 dmadev->device_terminate_all = sa11x0_dma_device_terminate_all; in sa11x0_dma_init_dmadev()
847 dmadev->device_tx_status = sa11x0_dma_tx_status; in sa11x0_dma_init_dmadev()
848 dmadev->device_issue_pending = sa11x0_dma_issue_pending; in sa11x0_dma_init_dmadev()
856 return -ENOMEM; in sa11x0_dma_init_dmadev()
859 c->status = DMA_IN_PROGRESS; in sa11x0_dma_init_dmadev()
860 c->ddar = chan_desc[i].ddar; in sa11x0_dma_init_dmadev()
861 c->name = chan_desc[i].name; in sa11x0_dma_init_dmadev()
862 INIT_LIST_HEAD(&c->node); in sa11x0_dma_init_dmadev()
864 c->vc.desc_free = sa11x0_dma_free_desc; in sa11x0_dma_init_dmadev()
865 vchan_init(&c->vc, dmadev); in sa11x0_dma_init_dmadev()
877 return -ENXIO; in sa11x0_dma_request_irq()
879 return request_irq(irq, sa11x0_dma_irq, 0, dev_name(&pdev->dev), data); in sa11x0_dma_request_irq()
894 list_for_each_entry_safe(c, cn, &dmadev->channels, vc.chan.device_node) { in sa11x0_dma_free_channels()
895 list_del(&c->vc.chan.device_node); in sa11x0_dma_free_channels()
896 tasklet_kill(&c->vc.task); in sa11x0_dma_free_channels()
910 return -ENXIO; in sa11x0_dma_probe()
914 ret = -ENOMEM; in sa11x0_dma_probe()
918 spin_lock_init(&d->lock); in sa11x0_dma_probe()
919 INIT_LIST_HEAD(&d->chan_pending); in sa11x0_dma_probe()
921 d->slave.filter.fn = sa11x0_dma_filter_fn; in sa11x0_dma_probe()
922 d->slave.filter.mapcnt = ARRAY_SIZE(sa11x0_dma_map); in sa11x0_dma_probe()
923 d->slave.filter.map = sa11x0_dma_map; in sa11x0_dma_probe()
925 d->base = ioremap(res->start, resource_size(res)); in sa11x0_dma_probe()
926 if (!d->base) { in sa11x0_dma_probe()
927 ret = -ENOMEM; in sa11x0_dma_probe()
931 tasklet_setup(&d->task, sa11x0_dma_tasklet); in sa11x0_dma_probe()
934 struct sa11x0_dma_phy *p = &d->phy[i]; in sa11x0_dma_probe()
936 p->dev = d; in sa11x0_dma_probe()
937 p->num = i; in sa11x0_dma_probe()
938 p->base = d->base + i * DMA_SIZE; in sa11x0_dma_probe()
941 p->base + DMA_DCSR_C); in sa11x0_dma_probe()
942 writel_relaxed(0, p->base + DMA_DDAR); in sa11x0_dma_probe()
947 i--; in sa11x0_dma_probe()
948 sa11x0_dma_free_irq(pdev, i, &d->phy[i]); in sa11x0_dma_probe()
954 dma_cap_set(DMA_SLAVE, d->slave.cap_mask); in sa11x0_dma_probe()
955 dma_cap_set(DMA_CYCLIC, d->slave.cap_mask); in sa11x0_dma_probe()
956 d->slave.device_prep_slave_sg = sa11x0_dma_prep_slave_sg; in sa11x0_dma_probe()
957 d->slave.device_prep_dma_cyclic = sa11x0_dma_prep_dma_cyclic; in sa11x0_dma_probe()
958 d->slave.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); in sa11x0_dma_probe()
959 d->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; in sa11x0_dma_probe()
960 d->slave.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | in sa11x0_dma_probe()
962 d->slave.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | in sa11x0_dma_probe()
964 ret = sa11x0_dma_init_dmadev(&d->slave, &pdev->dev); in sa11x0_dma_probe()
966 dev_warn(d->slave.dev, "failed to register slave async device: %d\n", in sa11x0_dma_probe()
975 sa11x0_dma_free_channels(&d->slave); in sa11x0_dma_probe()
977 sa11x0_dma_free_irq(pdev, i, &d->phy[i]); in sa11x0_dma_probe()
979 tasklet_kill(&d->task); in sa11x0_dma_probe()
980 iounmap(d->base); in sa11x0_dma_probe()
992 dma_async_device_unregister(&d->slave); in sa11x0_dma_remove()
994 sa11x0_dma_free_channels(&d->slave); in sa11x0_dma_remove()
996 sa11x0_dma_free_irq(pdev, pch, &d->phy[pch]); in sa11x0_dma_remove()
997 tasklet_kill(&d->task); in sa11x0_dma_remove()
998 iounmap(d->base); in sa11x0_dma_remove()
1008 struct sa11x0_dma_phy *p = &d->phy[pch]; in sa11x0_dma_suspend()
1011 dcsr = saved_dcsr = readl_relaxed(p->base + DMA_DCSR_R); in sa11x0_dma_suspend()
1013 writel(DCSR_RUN | DCSR_IE, p->base + DMA_DCSR_C); in sa11x0_dma_suspend()
1014 dcsr = readl_relaxed(p->base + DMA_DCSR_R); in sa11x0_dma_suspend()
1019 p->dbs[0] = readl_relaxed(p->base + DMA_DBSB); in sa11x0_dma_suspend()
1020 p->dbt[0] = readl_relaxed(p->base + DMA_DBTB); in sa11x0_dma_suspend()
1021 p->dbs[1] = readl_relaxed(p->base + DMA_DBSA); in sa11x0_dma_suspend()
1022 p->dbt[1] = readl_relaxed(p->base + DMA_DBTA); in sa11x0_dma_suspend()
1026 p->dbs[0] = readl_relaxed(p->base + DMA_DBSA); in sa11x0_dma_suspend()
1027 p->dbt[0] = readl_relaxed(p->base + DMA_DBTA); in sa11x0_dma_suspend()
1028 p->dbs[1] = readl_relaxed(p->base + DMA_DBSB); in sa11x0_dma_suspend()
1029 p->dbt[1] = readl_relaxed(p->base + DMA_DBTB); in sa11x0_dma_suspend()
1032 p->dcsr = saved_dcsr; in sa11x0_dma_suspend()
1034 writel(DCSR_STRTA | DCSR_STRTB, p->base + DMA_DCSR_C); in sa11x0_dma_suspend()
1046 struct sa11x0_dma_phy *p = &d->phy[pch]; in sa11x0_dma_resume()
1048 u32 dcsr = readl_relaxed(p->base + DMA_DCSR_R); in sa11x0_dma_resume()
1052 if (p->txd_done) in sa11x0_dma_resume()
1053 txd = p->txd_done; in sa11x0_dma_resume()
1054 else if (p->txd_load) in sa11x0_dma_resume()
1055 txd = p->txd_load; in sa11x0_dma_resume()
1060 writel_relaxed(txd->ddar, p->base + DMA_DDAR); in sa11x0_dma_resume()
1062 writel_relaxed(p->dbs[0], p->base + DMA_DBSA); in sa11x0_dma_resume()
1063 writel_relaxed(p->dbt[0], p->base + DMA_DBTA); in sa11x0_dma_resume()
1064 writel_relaxed(p->dbs[1], p->base + DMA_DBSB); in sa11x0_dma_resume()
1065 writel_relaxed(p->dbt[1], p->base + DMA_DBTB); in sa11x0_dma_resume()
1066 writel_relaxed(p->dcsr, p->base + DMA_DCSR_S); in sa11x0_dma_resume()
1078 .name = "sa11x0-dma",
1098 MODULE_DESCRIPTION("SA-11x0 DMA driver");
1100 MODULE_ALIAS("platform:sa11x0-dma");