| .. | .. |
|---|
| 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 | |
|---|