Lines Matching +full:socfpga +full:- +full:msgdma

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * DMA driver for Altera mSGDMA IP core
13 #include <linux/dma-mapping.h>
30 * struct msgdma_extended_desc - implements an extended descriptor
54 /* mSGDMA descriptor control field bit definitions */
99 /* mSGDMA extended descriptor stride definitions */
104 /* mSGDMA dispatcher control and status register map */
107 #define MSGDMA_CSR_RW_FILL_LEVEL 0x08 /* 31:16 - write fill level */
108 /* 15:00 - read fill level */
110 #define MSGDMA_CSR_RW_SEQ_NUM 0x10 /* 31:16 - write seq number */
111 /* 15:00 - read seq number */
113 /* mSGDMA CSR status register bit definitions */
130 /* mSGDMA CSR control register bit definitions */
138 /* mSGDMA CSR fill level bits */
145 /* mSGDMA response register map */
149 /* mSGDMA response register bit definitions */
154 * struct msgdma_sw_desc - implements a sw descriptor
168 * struct msgdma_device - DMA device structure
191 /* mSGDMA controller */
194 /* mSGDMA descriptors */
197 /* mSGDMA response */
205 * msgdma_get_descriptor - Get the sw descriptor from the pool
206 * @mdev: Pointer to the Altera mSGDMA device structure
215 spin_lock_irqsave(&mdev->lock, flags); in msgdma_get_descriptor()
216 desc = list_first_entry(&mdev->free_list, struct msgdma_sw_desc, node); in msgdma_get_descriptor()
217 list_del(&desc->node); in msgdma_get_descriptor()
218 spin_unlock_irqrestore(&mdev->lock, flags); in msgdma_get_descriptor()
220 INIT_LIST_HEAD(&desc->tx_list); in msgdma_get_descriptor()
226 * msgdma_free_descriptor - Issue pending transactions
227 * @mdev: Pointer to the Altera mSGDMA device structure
235 mdev->desc_free_cnt++; in msgdma_free_descriptor()
236 list_move_tail(&desc->node, &mdev->free_list); in msgdma_free_descriptor()
237 list_for_each_entry_safe(child, next, &desc->tx_list, node) { in msgdma_free_descriptor()
238 mdev->desc_free_cnt++; in msgdma_free_descriptor()
239 list_move_tail(&child->node, &mdev->free_list); in msgdma_free_descriptor()
244 * msgdma_free_desc_list - Free descriptors list
245 * @mdev: Pointer to the Altera mSGDMA device structure
258 * msgdma_desc_config - Configure the descriptor
270 desc->read_addr_lo = lower_32_bits(src); in msgdma_desc_config()
271 desc->write_addr_lo = lower_32_bits(dst); in msgdma_desc_config()
274 desc->read_addr_hi = upper_32_bits(src); in msgdma_desc_config()
275 desc->write_addr_hi = upper_32_bits(dst); in msgdma_desc_config()
277 desc->len = len; in msgdma_desc_config()
278 desc->stride = stride; in msgdma_desc_config()
279 desc->burst_seq_num = 0; /* 0 will result in max burst length */ in msgdma_desc_config()
285 desc->control = MSGDMA_DESC_CTL_TR_ERR_IRQ | MSGDMA_DESC_CTL_GO | in msgdma_desc_config()
290 * msgdma_desc_config_eod - Mark the descriptor as end descriptor
295 desc->control |= MSGDMA_DESC_CTL_TR_COMP_IRQ; in msgdma_desc_config_eod()
299 * msgdma_tx_submit - Submit DMA transaction
306 struct msgdma_device *mdev = to_mdev(tx->chan); in msgdma_tx_submit()
312 spin_lock_irqsave(&mdev->lock, flags); in msgdma_tx_submit()
315 list_add_tail(&new->node, &mdev->pending_list); in msgdma_tx_submit()
316 spin_unlock_irqrestore(&mdev->lock, flags); in msgdma_tx_submit()
322 * msgdma_prep_memcpy - prepare descriptors for memcpy transaction
344 spin_lock_irqsave(&mdev->lock, irqflags); in msgdma_prep_memcpy()
345 if (desc_cnt > mdev->desc_free_cnt) { in msgdma_prep_memcpy()
346 spin_unlock_irqrestore(&mdev->lock, irqflags); in msgdma_prep_memcpy()
347 dev_dbg(mdev->dev, "mdev %p descs are not available\n", mdev); in msgdma_prep_memcpy()
350 mdev->desc_free_cnt -= desc_cnt; in msgdma_prep_memcpy()
351 spin_unlock_irqrestore(&mdev->lock, irqflags); in msgdma_prep_memcpy()
358 desc = &new->hw_desc; in msgdma_prep_memcpy()
361 len -= copy; in msgdma_prep_memcpy()
367 list_add_tail(&new->node, &first->tx_list); in msgdma_prep_memcpy()
371 async_tx_ack(&first->async_tx); in msgdma_prep_memcpy()
372 first->async_tx.flags = flags; in msgdma_prep_memcpy()
374 return &first->async_tx; in msgdma_prep_memcpy()
378 * msgdma_prep_slave_sg - prepare descriptors for a slave sg transaction
394 struct dma_slave_config *cfg = &mdev->slave_cfg; in msgdma_prep_slave_sg()
407 spin_lock_irqsave(&mdev->lock, irqflags); in msgdma_prep_slave_sg()
408 if (desc_cnt > mdev->desc_free_cnt) { in msgdma_prep_slave_sg()
409 spin_unlock_irqrestore(&mdev->lock, irqflags); in msgdma_prep_slave_sg()
410 dev_dbg(mdev->dev, "mdev %p descs are not available\n", mdev); in msgdma_prep_slave_sg()
413 mdev->desc_free_cnt -= desc_cnt; in msgdma_prep_slave_sg()
414 spin_unlock_irqrestore(&mdev->lock, irqflags); in msgdma_prep_slave_sg()
423 desc = &new->hw_desc; in msgdma_prep_slave_sg()
427 dma_src = sg_dma_address(sgl) + sg_dma_len(sgl) - avail; in msgdma_prep_slave_sg()
428 dma_dst = cfg->dst_addr; in msgdma_prep_slave_sg()
431 dma_src = cfg->src_addr; in msgdma_prep_slave_sg()
432 dma_dst = sg_dma_address(sgl) + sg_dma_len(sgl) - avail; in msgdma_prep_slave_sg()
436 avail -= len; in msgdma_prep_slave_sg()
441 list_add_tail(&new->node, &first->tx_list); in msgdma_prep_slave_sg()
450 sg_len--; in msgdma_prep_slave_sg()
456 first->async_tx.flags = flags; in msgdma_prep_slave_sg()
458 return &first->async_tx; in msgdma_prep_slave_sg()
466 memcpy(&mdev->slave_cfg, config, sizeof(*config)); in msgdma_dma_config()
476 /* Reset mSGDMA */ in msgdma_reset()
477 iowrite32(MSGDMA_CSR_STAT_MASK, mdev->csr + MSGDMA_CSR_STATUS); in msgdma_reset()
478 iowrite32(MSGDMA_CSR_CTL_RESET, mdev->csr + MSGDMA_CSR_CONTROL); in msgdma_reset()
480 ret = readl_poll_timeout(mdev->csr + MSGDMA_CSR_STATUS, val, in msgdma_reset()
484 dev_err(mdev->dev, "DMA channel did not reset\n"); in msgdma_reset()
487 iowrite32(MSGDMA_CSR_STAT_MASK, mdev->csr + MSGDMA_CSR_STATUS); in msgdma_reset()
491 MSGDMA_CSR_CTL_GLOBAL_INTR, mdev->csr + MSGDMA_CSR_CONTROL); in msgdma_reset()
493 mdev->idle = true; in msgdma_reset()
499 void __iomem *hw_desc = mdev->desc; in msgdma_copy_one()
505 while (ioread32(mdev->csr + MSGDMA_CSR_STATUS) & in msgdma_copy_one()
516 * adding some write-barriers here. in msgdma_copy_one()
518 memcpy((void __force *)hw_desc, &desc->hw_desc, in msgdma_copy_one()
519 sizeof(desc->hw_desc) - sizeof(u32)); in msgdma_copy_one()
522 mdev->idle = false; in msgdma_copy_one()
524 iowrite32(desc->hw_desc.control, hw_desc + in msgdma_copy_one()
530 * msgdma_copy_desc_to_fifo - copy descriptor(s) into controller FIFO
531 * @mdev: Pointer to the Altera mSGDMA device structure
541 list_for_each_entry_safe(sdesc, next, &desc->tx_list, node) in msgdma_copy_desc_to_fifo()
546 * msgdma_start_transfer - Initiate the new transfer
547 * @mdev: Pointer to the Altera mSGDMA device structure
553 if (!mdev->idle) in msgdma_start_transfer()
556 desc = list_first_entry_or_null(&mdev->pending_list, in msgdma_start_transfer()
561 list_splice_tail_init(&mdev->pending_list, &mdev->active_list); in msgdma_start_transfer()
566 * msgdma_issue_pending - Issue pending transactions
574 spin_lock_irqsave(&mdev->lock, flags); in msgdma_issue_pending()
576 spin_unlock_irqrestore(&mdev->lock, flags); in msgdma_issue_pending()
580 * msgdma_chan_desc_cleanup - Cleanup the completed descriptors
581 * @mdev: Pointer to the Altera mSGDMA device structure
588 spin_lock_irqsave(&mdev->lock, irqflags); in msgdma_chan_desc_cleanup()
590 list_for_each_entry_safe(desc, next, &mdev->done_list, node) { in msgdma_chan_desc_cleanup()
593 dmaengine_desc_get_callback(&desc->async_tx, &cb); in msgdma_chan_desc_cleanup()
595 spin_unlock_irqrestore(&mdev->lock, irqflags); in msgdma_chan_desc_cleanup()
597 spin_lock_irqsave(&mdev->lock, irqflags); in msgdma_chan_desc_cleanup()
604 spin_unlock_irqrestore(&mdev->lock, irqflags); in msgdma_chan_desc_cleanup()
608 * msgdma_complete_descriptor - Mark the active descriptor as complete
609 * @mdev: Pointer to the Altera mSGDMA device structure
615 desc = list_first_entry_or_null(&mdev->active_list, in msgdma_complete_descriptor()
619 list_del(&desc->node); in msgdma_complete_descriptor()
620 dma_cookie_complete(&desc->async_tx); in msgdma_complete_descriptor()
621 list_add_tail(&desc->node, &mdev->done_list); in msgdma_complete_descriptor()
625 * msgdma_free_descriptors - Free channel descriptors
626 * @mdev: Pointer to the Altera mSGDMA device structure
630 msgdma_free_desc_list(mdev, &mdev->active_list); in msgdma_free_descriptors()
631 msgdma_free_desc_list(mdev, &mdev->pending_list); in msgdma_free_descriptors()
632 msgdma_free_desc_list(mdev, &mdev->done_list); in msgdma_free_descriptors()
636 * msgdma_free_chan_resources - Free channel resources
644 spin_lock_irqsave(&mdev->lock, flags); in msgdma_free_chan_resources()
646 spin_unlock_irqrestore(&mdev->lock, flags); in msgdma_free_chan_resources()
647 kfree(mdev->sw_desq); in msgdma_free_chan_resources()
651 * msgdma_alloc_chan_resources - Allocate channel resources
662 mdev->sw_desq = kcalloc(MSGDMA_DESC_NUM, sizeof(*desc), GFP_NOWAIT); in msgdma_alloc_chan_resources()
663 if (!mdev->sw_desq) in msgdma_alloc_chan_resources()
664 return -ENOMEM; in msgdma_alloc_chan_resources()
666 mdev->idle = true; in msgdma_alloc_chan_resources()
667 mdev->desc_free_cnt = MSGDMA_DESC_NUM; in msgdma_alloc_chan_resources()
669 INIT_LIST_HEAD(&mdev->free_list); in msgdma_alloc_chan_resources()
672 desc = mdev->sw_desq + i; in msgdma_alloc_chan_resources()
673 dma_async_tx_descriptor_init(&desc->async_tx, &mdev->dmachan); in msgdma_alloc_chan_resources()
674 desc->async_tx.tx_submit = msgdma_tx_submit; in msgdma_alloc_chan_resources()
675 list_add_tail(&desc->node, &mdev->free_list); in msgdma_alloc_chan_resources()
682 * msgdma_tasklet - Schedule completion tasklet
693 spin_lock_irqsave(&mdev->lock, flags); in msgdma_tasklet()
695 if (mdev->resp) { in msgdma_tasklet()
697 count = ioread32(mdev->csr + MSGDMA_CSR_RESP_FILL_LEVEL); in msgdma_tasklet()
698 dev_dbg(mdev->dev, "%s (%d): response count=%d\n", in msgdma_tasklet()
704 while (count--) { in msgdma_tasklet()
707 * On Avalon-MM implementations, size and status do not in msgdma_tasklet()
711 if (mdev->resp) { in msgdma_tasklet()
712 size = ioread32(mdev->resp + in msgdma_tasklet()
714 status = ioread32(mdev->resp + in msgdma_tasklet()
721 spin_unlock_irqrestore(&mdev->lock, flags); in msgdma_tasklet()
727 * msgdma_irq_handler - Altera mSGDMA Interrupt handler
729 * @data: Pointer to the Altera mSGDMA device structure
738 status = ioread32(mdev->csr + MSGDMA_CSR_STATUS); in msgdma_irq_handler()
741 spin_lock(&mdev->lock); in msgdma_irq_handler()
742 mdev->idle = true; in msgdma_irq_handler()
744 spin_unlock(&mdev->lock); in msgdma_irq_handler()
747 tasklet_schedule(&mdev->irq_tasklet); in msgdma_irq_handler()
749 /* Clear interrupt in mSGDMA controller */ in msgdma_irq_handler()
750 iowrite32(MSGDMA_CSR_STAT_IRQ, mdev->csr + MSGDMA_CSR_STATUS); in msgdma_irq_handler()
756 * msgdma_dev_remove() - Device remove function
757 * @mdev: Pointer to the Altera mSGDMA device structure
764 devm_free_irq(mdev->dev, mdev->irq, mdev); in msgdma_dev_remove()
765 tasklet_kill(&mdev->irq_tasklet); in msgdma_dev_remove()
766 list_del(&mdev->dmachan.device_node); in msgdma_dev_remove()
774 struct device *device = &pdev->dev; in request_and_map()
785 return -ENODEV; in request_and_map()
788 region = devm_request_mem_region(device, (*res)->start, in request_and_map()
792 return -EBUSY; in request_and_map()
795 *ptr = devm_ioremap(device, region->start, in request_and_map()
799 return -ENOMEM; in request_and_map()
806 * msgdma_probe - Driver probe function
818 mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_NOWAIT); in msgdma_probe()
820 return -ENOMEM; in msgdma_probe()
822 mdev->dev = &pdev->dev; in msgdma_probe()
825 ret = request_and_map(pdev, "csr", &dma_res, &mdev->csr, false); in msgdma_probe()
830 ret = request_and_map(pdev, "desc", &dma_res, &mdev->desc, false); in msgdma_probe()
835 ret = request_and_map(pdev, "resp", &dma_res, &mdev->resp, true); in msgdma_probe()
842 mdev->irq = platform_get_irq(pdev, 0); in msgdma_probe()
843 if (mdev->irq < 0) in msgdma_probe()
844 return -ENXIO; in msgdma_probe()
846 ret = devm_request_irq(&pdev->dev, mdev->irq, msgdma_irq_handler, in msgdma_probe()
847 0, dev_name(&pdev->dev), mdev); in msgdma_probe()
851 tasklet_setup(&mdev->irq_tasklet, msgdma_tasklet); in msgdma_probe()
853 dma_cookie_init(&mdev->dmachan); in msgdma_probe()
855 spin_lock_init(&mdev->lock); in msgdma_probe()
857 INIT_LIST_HEAD(&mdev->active_list); in msgdma_probe()
858 INIT_LIST_HEAD(&mdev->pending_list); in msgdma_probe()
859 INIT_LIST_HEAD(&mdev->done_list); in msgdma_probe()
860 INIT_LIST_HEAD(&mdev->free_list); in msgdma_probe()
862 dma_dev = &mdev->dmadev; in msgdma_probe()
865 dma_cap_zero(dma_dev->cap_mask); in msgdma_probe()
866 dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask); in msgdma_probe()
867 dma_cap_set(DMA_SLAVE, dma_dev->cap_mask); in msgdma_probe()
869 dma_dev->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); in msgdma_probe()
870 dma_dev->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); in msgdma_probe()
871 dma_dev->directions = BIT(DMA_MEM_TO_DEV) | BIT(DMA_DEV_TO_MEM) | in msgdma_probe()
873 dma_dev->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR; in msgdma_probe()
876 INIT_LIST_HEAD(&dma_dev->channels); in msgdma_probe()
879 dma_dev->device_tx_status = dma_cookie_status; in msgdma_probe()
880 dma_dev->device_issue_pending = msgdma_issue_pending; in msgdma_probe()
881 dma_dev->dev = &pdev->dev; in msgdma_probe()
883 dma_dev->copy_align = DMAENGINE_ALIGN_4_BYTES; in msgdma_probe()
884 dma_dev->device_prep_dma_memcpy = msgdma_prep_memcpy; in msgdma_probe()
885 dma_dev->device_prep_slave_sg = msgdma_prep_slave_sg; in msgdma_probe()
886 dma_dev->device_config = msgdma_dma_config; in msgdma_probe()
888 dma_dev->device_alloc_chan_resources = msgdma_alloc_chan_resources; in msgdma_probe()
889 dma_dev->device_free_chan_resources = msgdma_free_chan_resources; in msgdma_probe()
891 mdev->dmachan.device = dma_dev; in msgdma_probe()
892 list_add_tail(&mdev->dmachan.device_node, &dma_dev->channels); in msgdma_probe()
895 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); in msgdma_probe()
897 dev_warn(&pdev->dev, "unable to set coherent mask to 64"); in msgdma_probe()
907 ret = of_dma_controller_register(pdev->dev.of_node, in msgdma_probe()
909 if (ret == -EINVAL) in msgdma_probe()
910 dev_warn(&pdev->dev, "device was not probed from DT"); in msgdma_probe()
911 else if (ret && ret != -ENODEV) in msgdma_probe()
914 dev_notice(&pdev->dev, "Altera mSGDMA driver probe success\n"); in msgdma_probe()
925 * msgdma_remove() - Driver remove function
934 if (pdev->dev.of_node) in msgdma_remove()
935 of_dma_controller_free(pdev->dev.of_node); in msgdma_remove()
936 dma_async_device_unregister(&mdev->dmadev); in msgdma_remove()
939 dev_notice(&pdev->dev, "Altera mSGDMA driver removed\n"); in msgdma_remove()
944 { .compatible = "altr,socfpga-msgdma", },
953 .name = "altera-msgdma",
962 MODULE_ALIAS("platform:altera-msgdma");
963 MODULE_DESCRIPTION("Altera mSGDMA driver");