.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright 2012 Marvell International Ltd. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License version 2 as |
---|
6 | | - * published by the Free Software Foundation. |
---|
7 | 4 | */ |
---|
8 | 5 | |
---|
9 | 6 | #include <linux/err.h> |
---|
.. | .. |
---|
96 | 93 | struct dma_async_tx_descriptor desc; |
---|
97 | 94 | struct mmp_pdma_phy *phy; |
---|
98 | 95 | enum dma_transfer_direction dir; |
---|
| 96 | + struct dma_slave_config slave_config; |
---|
99 | 97 | |
---|
100 | 98 | struct mmp_pdma_desc_sw *cyclic_first; /* first desc_sw if channel |
---|
101 | 99 | * is in cyclic mode */ |
---|
.. | .. |
---|
139 | 137 | container_of(dchan, struct mmp_pdma_chan, chan) |
---|
140 | 138 | #define to_mmp_pdma_dev(dmadev) \ |
---|
141 | 139 | container_of(dmadev, struct mmp_pdma_device, device) |
---|
| 140 | + |
---|
| 141 | +static int mmp_pdma_config_write(struct dma_chan *dchan, |
---|
| 142 | + struct dma_slave_config *cfg, |
---|
| 143 | + enum dma_transfer_direction direction); |
---|
142 | 144 | |
---|
143 | 145 | static void set_desc(struct mmp_pdma_phy *phy, dma_addr_t addr) |
---|
144 | 146 | { |
---|
.. | .. |
---|
288 | 290 | spin_unlock_irqrestore(&pdev->phy_lock, flags); |
---|
289 | 291 | } |
---|
290 | 292 | |
---|
291 | | -/** |
---|
| 293 | +/* |
---|
292 | 294 | * start_pending_queue - transfer any pending transactions |
---|
293 | 295 | * pending list ==> running list |
---|
294 | 296 | */ |
---|
.. | .. |
---|
379 | 381 | return desc; |
---|
380 | 382 | } |
---|
381 | 383 | |
---|
382 | | -/** |
---|
| 384 | +/* |
---|
383 | 385 | * mmp_pdma_alloc_chan_resources - Allocate resources for DMA channel. |
---|
384 | 386 | * |
---|
385 | 387 | * This function will create a dma pool for descriptor allocation. |
---|
.. | .. |
---|
537 | 539 | |
---|
538 | 540 | chan->byte_align = false; |
---|
539 | 541 | |
---|
| 542 | + mmp_pdma_config_write(dchan, &chan->slave_config, dir); |
---|
| 543 | + |
---|
540 | 544 | for_each_sg(sgl, sg, sg_len, i) { |
---|
541 | 545 | addr = sg_dma_address(sg); |
---|
542 | 546 | avail = sg_dma_len(sgl); |
---|
.. | .. |
---|
619 | 623 | return NULL; |
---|
620 | 624 | |
---|
621 | 625 | chan = to_mmp_pdma_chan(dchan); |
---|
| 626 | + mmp_pdma_config_write(dchan, &chan->slave_config, direction); |
---|
622 | 627 | |
---|
623 | 628 | switch (direction) { |
---|
624 | 629 | case DMA_MEM_TO_DEV: |
---|
.. | .. |
---|
684 | 689 | return NULL; |
---|
685 | 690 | } |
---|
686 | 691 | |
---|
687 | | -static int mmp_pdma_config(struct dma_chan *dchan, |
---|
688 | | - struct dma_slave_config *cfg) |
---|
| 692 | +static int mmp_pdma_config_write(struct dma_chan *dchan, |
---|
| 693 | + struct dma_slave_config *cfg, |
---|
| 694 | + enum dma_transfer_direction direction) |
---|
689 | 695 | { |
---|
690 | 696 | struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan); |
---|
691 | 697 | u32 maxburst = 0, addr = 0; |
---|
.. | .. |
---|
694 | 700 | if (!dchan) |
---|
695 | 701 | return -EINVAL; |
---|
696 | 702 | |
---|
697 | | - if (cfg->direction == DMA_DEV_TO_MEM) { |
---|
| 703 | + if (direction == DMA_DEV_TO_MEM) { |
---|
698 | 704 | chan->dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC; |
---|
699 | 705 | maxburst = cfg->src_maxburst; |
---|
700 | 706 | width = cfg->src_addr_width; |
---|
701 | 707 | addr = cfg->src_addr; |
---|
702 | | - } else if (cfg->direction == DMA_MEM_TO_DEV) { |
---|
| 708 | + } else if (direction == DMA_MEM_TO_DEV) { |
---|
703 | 709 | chan->dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG; |
---|
704 | 710 | maxburst = cfg->dst_maxburst; |
---|
705 | 711 | width = cfg->dst_addr_width; |
---|
.. | .. |
---|
720 | 726 | else if (maxburst == 32) |
---|
721 | 727 | chan->dcmd |= DCMD_BURST32; |
---|
722 | 728 | |
---|
723 | | - chan->dir = cfg->direction; |
---|
| 729 | + chan->dir = direction; |
---|
724 | 730 | chan->dev_addr = addr; |
---|
725 | 731 | |
---|
| 732 | + return 0; |
---|
| 733 | +} |
---|
| 734 | + |
---|
| 735 | +static int mmp_pdma_config(struct dma_chan *dchan, |
---|
| 736 | + struct dma_slave_config *cfg) |
---|
| 737 | +{ |
---|
| 738 | + struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan); |
---|
| 739 | + |
---|
| 740 | + memcpy(&chan->slave_config, cfg, sizeof(*cfg)); |
---|
726 | 741 | return 0; |
---|
727 | 742 | } |
---|
728 | 743 | |
---|
.. | .. |
---|
833 | 848 | return ret; |
---|
834 | 849 | } |
---|
835 | 850 | |
---|
836 | | -/** |
---|
| 851 | +/* |
---|
837 | 852 | * mmp_pdma_issue_pending - Issue the DMA start command |
---|
838 | 853 | * pending list ==> running list |
---|
839 | 854 | */ |
---|
.. | .. |
---|
852 | 867 | * Do call back |
---|
853 | 868 | * Start pending list |
---|
854 | 869 | */ |
---|
855 | | -static void dma_do_tasklet(unsigned long data) |
---|
| 870 | +static void dma_do_tasklet(struct tasklet_struct *t) |
---|
856 | 871 | { |
---|
857 | | - struct mmp_pdma_chan *chan = (struct mmp_pdma_chan *)data; |
---|
| 872 | + struct mmp_pdma_chan *chan = from_tasklet(chan, t, tasklet); |
---|
858 | 873 | struct mmp_pdma_desc_sw *desc, *_desc; |
---|
859 | 874 | LIST_HEAD(chain_cleanup); |
---|
860 | 875 | unsigned long flags; |
---|
.. | .. |
---|
924 | 939 | struct mmp_pdma_phy *phy; |
---|
925 | 940 | int i, irq = 0, irq_num = 0; |
---|
926 | 941 | |
---|
| 942 | + if (op->dev.of_node) |
---|
| 943 | + of_dma_controller_free(op->dev.of_node); |
---|
927 | 944 | |
---|
928 | 945 | for (i = 0; i < pdev->dma_channels; i++) { |
---|
929 | 946 | if (platform_get_irq(op, i) > 0) |
---|
.. | .. |
---|
970 | 987 | spin_lock_init(&chan->desc_lock); |
---|
971 | 988 | chan->dev = pdev->dev; |
---|
972 | 989 | chan->chan.device = &pdev->device; |
---|
973 | | - tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan); |
---|
| 990 | + tasklet_setup(&chan->tasklet, dma_do_tasklet); |
---|
974 | 991 | INIT_LIST_HEAD(&chan->chain_pending); |
---|
975 | 992 | INIT_LIST_HEAD(&chan->chain_running); |
---|
976 | 993 | |
---|
.. | .. |
---|
1037 | 1054 | pdev->dma_channels = dma_channels; |
---|
1038 | 1055 | |
---|
1039 | 1056 | for (i = 0; i < dma_channels; i++) { |
---|
1040 | | - if (platform_get_irq(op, i) > 0) |
---|
| 1057 | + if (platform_get_irq_optional(op, i) > 0) |
---|
1041 | 1058 | irq_num++; |
---|
1042 | 1059 | } |
---|
1043 | 1060 | |
---|