Merge tag 'dmaengine-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 19 Dec 2022 14:54:17 +0000 (08:54 -0600)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 19 Dec 2022 14:54:17 +0000 (08:54 -0600)
Pull dmaengine updates from Vinod Koul:
 "New support:

    - Qualcomm SDM670, SM6115 and SM6375 GPI controller support

    - Ingenic JZ4755 dmaengine support

    - Removal of iop-adma driver

  Updates:

   - Tegra support for dma-channel-mask

   - at_hdmac cleanup and virt-chan support for this driver"

* tag 'dmaengine-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (46 commits)
  dmaengine: Revert "dmaengine: remove s3c24xx driver"
  dmaengine: tegra: Add support for dma-channel-mask
  dt-bindings: dmaengine: Add dma-channel-mask to Tegra GPCDMA
  dmaengine: idxd: Remove linux/msi.h include
  dt-bindings: dmaengine: qcom: gpi: add compatible for SM6375
  dmaengine: idxd: Fix crc_val field for completion record
  dmaengine: at_hdmac: Convert driver to use virt-dma
  dmaengine: at_hdmac: Remove unused member of at_dma_chan
  dmaengine: at_hdmac: Rename "chan_common" to "dma_chan"
  dmaengine: at_hdmac: Rename "dma_common" to "dma_device"
  dmaengine: at_hdmac: Use bitfield access macros
  dmaengine: at_hdmac: Keep register definitions and structures private to at_hdmac.c
  dmaengine: at_hdmac: Set include entries in alphabetic order
  dmaengine: at_hdmac: Use pm_ptr()
  dmaengine: at_hdmac: Use devm_clk_get()
  dmaengine: at_hdmac: Use devm_platform_ioremap_resource
  dmaengine: at_hdmac: Use devm_kzalloc() and struct_size()
  dmaengine: at_hdmac: Introduce atc_get_llis_residue()
  dmaengine: at_hdmac: s/atc_get_bytes_left/atc_get_residue
  dmaengine: at_hdmac: Pass residue by address to avoid unnecessary implicit casts
  ...

29 files changed:
Documentation/ABI/stable/sysfs-driver-dma-idxd
Documentation/devicetree/bindings/dma/ingenic,dma.yaml
Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml
Documentation/devicetree/bindings/dma/qcom,gpi.yaml
Documentation/driver-api/driver-model/devres.rst
MAINTAINERS
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/apple-admac.c
drivers/dma/at_hdmac.c
drivers/dma/at_hdmac_regs.h [deleted file]
drivers/dma/dma-jz4780.c
drivers/dma/idma64.c
drivers/dma/idxd/device.c
drivers/dma/idxd/sysfs.c
drivers/dma/ioat/dma.c
drivers/dma/iop-adma.c [deleted file]
drivers/dma/iop-adma.h [deleted file]
drivers/dma/qcom/gpi.c
drivers/dma/sh/shdma-arm.h [deleted file]
drivers/dma/tegra186-gpc-dma.c
drivers/dma/ti/Kconfig
drivers/dma/ti/Makefile
drivers/dma/ti/k3-psil.c
drivers/dma/ti/k3-udma-glue.c
drivers/dma/ti/k3-udma.c
drivers/dma/xilinx/xilinx_dma.c
drivers/of/irq.c
include/uapi/linux/idxd.h

index 8e2c2c405db22d411b7f86f8c0af634b09a3f36a..3becc9a82bdf6fbb28012e84763811dd6c091450 100644 (file)
@@ -22,6 +22,7 @@ Date:           Oct 25, 2019
 KernelVersion:  5.6.0
 Contact:        dmaengine@vger.kernel.org
 Description:    The largest number of work descriptors in a batch.
+                It's not visible when the device does not support batch.
 
 What:           /sys/bus/dsa/devices/dsa<m>/max_work_queues_size
 Date:           Oct 25, 2019
@@ -49,6 +50,8 @@ Description:    The total number of read buffers supported by this device.
                The read buffers represent resources within the DSA
                implementation, and these resources are allocated by engines to
                support operations. See DSA spec v1.2 9.2.4 Total Read Buffers.
+               It's not visible when the device does not support Read Buffer
+               allocation control.
 
 What:           /sys/bus/dsa/devices/dsa<m>/max_transfer_size
 Date:           Oct 25, 2019
@@ -122,6 +125,8 @@ Contact:        dmaengine@vger.kernel.org
 Description:    The maximum number of read buffers that may be in use at
                one time by operations that access low bandwidth memory in the
                device. See DSA spec v1.2 9.2.8 GENCFG on Global Read Buffer Limit.
+               It's not visible when the device does not support Read Buffer
+               allocation control.
 
 What:          /sys/bus/dsa/devices/dsa<m>/cmd_status
 Date:          Aug 28, 2020
@@ -205,6 +210,7 @@ KernelVersion:      5.10.0
 Contact:       dmaengine@vger.kernel.org
 Description:   The max batch size for this workqueue. Cannot exceed device
                max batch size. Configurable parameter.
+               It's not visible when the device does not support batch.
 
 What:          /sys/bus/dsa/devices/wq<m>.<n>/ats_disable
 Date:          Nov 13, 2020
@@ -250,6 +256,8 @@ KernelVersion:      5.17.0
 Contact:       dmaengine@vger.kernel.org
 Description:   Enable the use of global read buffer limit for the group. See DSA
                spec v1.2 9.2.18 GRPCFG Use Global Read Buffer Limit.
+               It's not visible when the device does not support Read Buffer
+               allocation control.
 
 What:          /sys/bus/dsa/devices/group<m>.<n>/read_buffers_allowed
 Date:          Dec 10, 2021
@@ -258,6 +266,8 @@ Contact:    dmaengine@vger.kernel.org
 Description:   Indicates max number of read buffers that may be in use at one time
                by all engines in the group. See DSA spec v1.2 9.2.18 GRPCFG Read
                Buffers Allowed.
+               It's not visible when the device does not support Read Buffer
+               allocation control.
 
 What:          /sys/bus/dsa/devices/group<m>.<n>/read_buffers_reserved
 Date:          Dec 10, 2021
@@ -266,6 +276,8 @@ Contact:    dmaengine@vger.kernel.org
 Description:   Indicates the number of Read Buffers reserved for the use of
                engines in the group. See DSA spec v1.2 9.2.18 GRPCFG Read Buffers
                Reserved.
+               It's not visible when the device does not support Read Buffer
+               allocation control.
 
 What:          /sys/bus/dsa/devices/group<m>.<n>/desc_progress_limit
 Date:          Sept 14, 2022
index 3b0b3b919af8c2f2b42e5ca0774891baba42cce2..e42b8ce948db1948bff0c255dbf8c5dcfbe7345b 100644 (file)
@@ -18,6 +18,7 @@ properties:
       - enum:
           - ingenic,jz4740-dma
           - ingenic,jz4725b-dma
+          - ingenic,jz4755-dma
           - ingenic,jz4760-dma
           - ingenic,jz4760-bdma
           - ingenic,jz4760-mdma
index c8894476b6abf95a6183c1fb0dfbc78fb80ba6cb..851bd50ee67fe0020f4ac34356e47cce7cce8463 100644 (file)
@@ -39,7 +39,7 @@ properties:
       Should contain all of the per-channel DMA interrupts in
       ascending order with respect to the DMA channel index.
     minItems: 1
-    maxItems: 31
+    maxItems: 32
 
   resets:
     maxItems: 1
@@ -52,6 +52,9 @@ properties:
 
   dma-coherent: true
 
+  dma-channel-mask:
+    maxItems: 1
+
 required:
   - compatible
   - reg
@@ -60,6 +63,7 @@ required:
   - reset-names
   - "#dma-cells"
   - iommus
+  - dma-channel-mask
 
 additionalProperties: false
 
@@ -108,5 +112,6 @@ examples:
         #dma-cells = <1>;
         iommus = <&smmu TEGRA186_SID_GPCDMA_0>;
         dma-coherent;
+        dma-channel-mask = <0xfffffffe>;
     };
 ...
index eabf8a76d3a05a6a88a6fecefdae5c4b00ada7a4..e7ba1c47a88eacce37ee4e3e42f6a5de955d8569 100644 (file)
@@ -18,14 +18,24 @@ allOf:
 
 properties:
   compatible:
-    enum:
-      - qcom,sc7280-gpi-dma
-      - qcom,sdm845-gpi-dma
-      - qcom,sm6350-gpi-dma
-      - qcom,sm8150-gpi-dma
-      - qcom,sm8250-gpi-dma
-      - qcom,sm8350-gpi-dma
-      - qcom,sm8450-gpi-dma
+    oneOf:
+      - enum:
+          - qcom,sdm845-gpi-dma
+          - qcom,sm6350-gpi-dma
+      - items:
+          - enum:
+              - qcom,sc7280-gpi-dma
+              - qcom,sm6115-gpi-dma
+              - qcom,sm6375-gpi-dma
+              - qcom,sm8350-gpi-dma
+              - qcom,sm8450-gpi-dma
+          - const: qcom,sm6350-gpi-dma
+      - items:
+          - enum:
+              - qcom,sdm670-gpi-dma
+              - qcom,sm8150-gpi-dma
+              - qcom,sm8250-gpi-dma
+          - const: qcom,sdm845-gpi-dma
 
   reg:
     maxItems: 1
index d2ef9fb34b7b094eda9419ea154f0a6a38fc7c06..4249eb4239e07c80bb30574495ad5bcbd0534569 100644 (file)
@@ -450,6 +450,7 @@ SERDEV
 
 SLAVE DMA ENGINE
   devm_acpi_dma_controller_register()
+  devm_acpi_dma_controller_free()
 
 SPI
   devm_spi_alloc_master()
index 204aeacc516b26a435700019c4f706556462584e..9737e8dd2e8b594f656aea5650a11907bdbd70d1 100644 (file)
@@ -10460,11 +10460,6 @@ T:     git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
 F:     drivers/iommu/intel/
 F:     include/linux/intel-svm.h
 
-INTEL IOP-ADMA DMA DRIVER
-R:     Dan Williams <dan.j.williams@intel.com>
-S:     Odd fixes
-F:     drivers/dma/iop-adma.c
-
 INTEL IPU3 CSI-2 CIO2 DRIVER
 M:     Yong Zhi <yong.zhi@intel.com>
 M:     Sakari Ailus <sakari.ailus@linux.intel.com>
@@ -13629,7 +13624,6 @@ L:      dmaengine@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/dma/atmel-dma.txt
 F:     drivers/dma/at_hdmac.c
-F:     drivers/dma/at_hdmac_regs.h
 F:     drivers/dma/at_xdmac.c
 F:     include/dt-bindings/dma/at91.h
 
index 25e111ab21f83089f0076a6d185fb6931ac64867..b6d48d54f42fcffda66ccb2ac2e5e01a15502d37 100644 (file)
@@ -97,6 +97,7 @@ config AT_HDMAC
        tristate "Atmel AHB DMA support"
        depends on ARCH_AT91
        select DMA_ENGINE
+       select DMA_VIRTUAL_CHANNELS
        help
          Support the Atmel AHB DMA controller.
 
@@ -357,14 +358,6 @@ config INTEL_IOATDMA
 
          If unsure, say N.
 
-config INTEL_IOP_ADMA
-       tristate "Intel IOP32x ADMA support"
-       depends on ARCH_IOP32X || COMPILE_TEST
-       select DMA_ENGINE
-       select ASYNC_TX_ENABLE_CHANNEL_SWITCH
-       help
-         Enable support for the Intel(R) IOP Series RAID engines.
-
 config K3_DMA
        tristate "Hisilicon K3 DMA support"
        depends on ARCH_HI3xxx || ARCH_HISI || COMPILE_TEST
index 10f7d424100176932e11dbd5198a3ea3dad93e99..5b55ada052a7ff5c48e6eac2fcb9fc5ca68bab44 100644 (file)
@@ -44,7 +44,6 @@ obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
 obj-$(CONFIG_INTEL_IDMA64) += idma64.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-y += idxd/
-obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_K3_DMA) += k3dma.o
 obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o
 obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o
index a2cc520225d32850db821ff0a8b7633a86343ddb..90f28bda29c8bd41e19b340e779c351634d29283 100644 (file)
 #define NCHANNELS_MAX  64
 #define IRQ_NOUTPUTS   4
 
+/*
+ * For allocation purposes we split the cache
+ * memory into blocks of fixed size (given in bytes).
+ */
+#define SRAM_BLOCK     2048
+
 #define RING_WRITE_SLOT                GENMASK(1, 0)
 #define RING_READ_SLOT         GENMASK(5, 4)
 #define RING_FULL              BIT(9)
@@ -36,6 +42,9 @@
 #define REG_TX_STOP            0x0004
 #define REG_RX_START           0x0008
 #define REG_RX_STOP            0x000c
+#define REG_IMPRINT            0x0090
+#define REG_TX_SRAM_SIZE       0x0094
+#define REG_RX_SRAM_SIZE       0x0098
 
 #define REG_CHAN_CTL(ch)       (0x8000 + (ch) * 0x200)
 #define REG_CHAN_CTL_RST_RINGS BIT(0)
@@ -53,7 +62,9 @@
 #define BUS_WIDTH_FRAME_2_WORDS        0x10
 #define BUS_WIDTH_FRAME_4_WORDS        0x20
 
-#define CHAN_BUFSIZE           0x8000
+#define REG_CHAN_SRAM_CARVEOUT(ch)     (0x8050 + (ch) * 0x200)
+#define CHAN_SRAM_CARVEOUT_SIZE                GENMASK(31, 16)
+#define CHAN_SRAM_CARVEOUT_BASE                GENMASK(15, 0)
 
 #define REG_CHAN_FIFOCTL(ch)   (0x8054 + (ch) * 0x200)
 #define CHAN_FIFOCTL_LIMIT     GENMASK(31, 16)
@@ -76,6 +87,8 @@ struct admac_chan {
        struct dma_chan chan;
        struct tasklet_struct tasklet;
 
+       u32 carveout;
+
        spinlock_t lock;
        struct admac_tx *current_tx;
        int nperiod_acks;
@@ -92,12 +105,24 @@ struct admac_chan {
        struct list_head to_free;
 };
 
+struct admac_sram {
+       u32 size;
+       /*
+        * SRAM_CARVEOUT has 16-bit fields, so the SRAM cannot be larger than
+        * 64K and a 32-bit bitfield over 2K blocks covers it.
+        */
+       u32 allocated;
+};
+
 struct admac_data {
        struct dma_device dma;
        struct device *dev;
        __iomem void *base;
        struct reset_control *rstc;
 
+       struct mutex cache_alloc_lock;
+       struct admac_sram txcache, rxcache;
+
        int irq;
        int irq_index;
        int nchannels;
@@ -118,6 +143,60 @@ struct admac_tx {
        struct list_head node;
 };
 
+static int admac_alloc_sram_carveout(struct admac_data *ad,
+                                    enum dma_transfer_direction dir,
+                                    u32 *out)
+{
+       struct admac_sram *sram;
+       int i, ret = 0, nblocks;
+
+       if (dir == DMA_MEM_TO_DEV)
+               sram = &ad->txcache;
+       else
+               sram = &ad->rxcache;
+
+       mutex_lock(&ad->cache_alloc_lock);
+
+       nblocks = sram->size / SRAM_BLOCK;
+       for (i = 0; i < nblocks; i++)
+               if (!(sram->allocated & BIT(i)))
+                       break;
+
+       if (i < nblocks) {
+               *out = FIELD_PREP(CHAN_SRAM_CARVEOUT_BASE, i * SRAM_BLOCK) |
+                       FIELD_PREP(CHAN_SRAM_CARVEOUT_SIZE, SRAM_BLOCK);
+               sram->allocated |= BIT(i);
+       } else {
+               ret = -EBUSY;
+       }
+
+       mutex_unlock(&ad->cache_alloc_lock);
+
+       return ret;
+}
+
+static void admac_free_sram_carveout(struct admac_data *ad,
+                                    enum dma_transfer_direction dir,
+                                    u32 carveout)
+{
+       struct admac_sram *sram;
+       u32 base = FIELD_GET(CHAN_SRAM_CARVEOUT_BASE, carveout);
+       int i;
+
+       if (dir == DMA_MEM_TO_DEV)
+               sram = &ad->txcache;
+       else
+               sram = &ad->rxcache;
+
+       if (WARN_ON(base >= sram->size))
+               return;
+
+       mutex_lock(&ad->cache_alloc_lock);
+       i = base / SRAM_BLOCK;
+       sram->allocated &= ~BIT(i);
+       mutex_unlock(&ad->cache_alloc_lock);
+}
+
 static void admac_modify(struct admac_data *ad, int reg, u32 mask, u32 val)
 {
        void __iomem *addr = ad->base + reg;
@@ -466,15 +545,28 @@ static void admac_synchronize(struct dma_chan *chan)
 static int admac_alloc_chan_resources(struct dma_chan *chan)
 {
        struct admac_chan *adchan = to_admac_chan(chan);
+       struct admac_data *ad = adchan->host;
+       int ret;
 
        dma_cookie_init(&adchan->chan);
+       ret = admac_alloc_sram_carveout(ad, admac_chan_direction(adchan->no),
+                                       &adchan->carveout);
+       if (ret < 0)
+               return ret;
+
+       writel_relaxed(adchan->carveout,
+                      ad->base + REG_CHAN_SRAM_CARVEOUT(adchan->no));
        return 0;
 }
 
 static void admac_free_chan_resources(struct dma_chan *chan)
 {
+       struct admac_chan *adchan = to_admac_chan(chan);
+
        admac_terminate_all(chan);
        admac_synchronize(chan);
+       admac_free_sram_carveout(adchan->host, admac_chan_direction(adchan->no),
+                                adchan->carveout);
 }
 
 static struct dma_chan *admac_dma_of_xlate(struct of_phandle_args *dma_spec,
@@ -712,6 +804,7 @@ static int admac_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, ad);
        ad->dev = &pdev->dev;
        ad->nchannels = nchannels;
+       mutex_init(&ad->cache_alloc_lock);
 
        /*
         * The controller has 4 IRQ outputs. Try them all until
@@ -801,6 +894,13 @@ static int admac_probe(struct platform_device *pdev)
                goto free_irq;
        }
 
+       ad->txcache.size = readl_relaxed(ad->base + REG_TX_SRAM_SIZE);
+       ad->rxcache.size = readl_relaxed(ad->base + REG_RX_SRAM_SIZE);
+
+       dev_info(&pdev->dev, "Audio DMA Controller\n");
+       dev_info(&pdev->dev, "imprint %x TX cache %u RX cache %u\n",
+                readl_relaxed(ad->base + REG_IMPRINT), ad->txcache.size, ad->rxcache.size);
+
        return 0;
 
 free_irq:
index 858bd64f13135f1370a59d2290570189de89415c..8858470246e1552e5e278a2b254f8ae874df894b 100644 (file)
@@ -3,6 +3,7 @@
  * Driver for the Atmel AHB DMA Controller (aka HDMA or DMAC on AT91 systems)
  *
  * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2022 Microchip Technology, Inc. and its subsidiaries
  *
  * This supports the Atmel AHB DMA Controller found in several Atmel SoCs.
  * The only Atmel DMA Controller that is not covered by this driver is the one
  */
 
 #include <dt-bindings/dma/at91.h>
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/dmaengine.h>
-#include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/overflow.h>
 #include <linux/of_device.h>
 #include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
 
-#include "at_hdmac_regs.h"
 #include "dmaengine.h"
+#include "virt-dma.h"
 
 /*
  * Glossary
  * atc_        / atchan        : ATmel DMA Channel entity related
  */
 
-#define        ATC_DEFAULT_CFG         (ATC_FIFOCFG_HALFFIFO)
-#define        ATC_DEFAULT_CTRLB       (ATC_SIF(AT_DMA_MEM_IF) \
-                               |ATC_DIF(AT_DMA_MEM_IF))
+#define        AT_DMA_MAX_NR_CHANNELS  8
+
+/* Global Configuration Register */
+#define AT_DMA_GCFG            0x00
+#define AT_DMA_IF_BIGEND(i)    BIT((i))        /* AHB-Lite Interface i in Big-endian mode */
+#define AT_DMA_ARB_CFG         BIT(4)          /* Arbiter mode. */
+
+/* Controller Enable Register */
+#define AT_DMA_EN              0x04
+#define AT_DMA_ENABLE          BIT(0)
+
+/* Software Single Request Register */
+#define AT_DMA_SREQ            0x08
+#define AT_DMA_SSREQ(x)                BIT((x) << 1)           /* Request a source single transfer on channel x */
+#define AT_DMA_DSREQ(x)                BIT(1 + ((x) << 1))     /* Request a destination single transfer on channel x */
+
+/* Software Chunk Transfer Request Register */
+#define AT_DMA_CREQ            0x0c
+#define AT_DMA_SCREQ(x)                BIT((x) << 1)           /* Request a source chunk transfer on channel x */
+#define AT_DMA_DCREQ(x)                BIT(1 + ((x) << 1))     /* Request a destination chunk transfer on channel x */
+
+/* Software Last Transfer Flag Register */
+#define AT_DMA_LAST            0x10
+#define AT_DMA_SLAST(x)                BIT((x) << 1)           /* This src rq is last tx of buffer on channel x */
+#define AT_DMA_DLAST(x)                BIT(1 + ((x) << 1))     /* This dst rq is last tx of buffer on channel x */
+
+/* Request Synchronization Register */
+#define AT_DMA_SYNC            0x14
+#define AT_DMA_SYR(h)          BIT((h))                /* Synchronize handshake line h */
+
+/* Error, Chained Buffer transfer completed and Buffer transfer completed Interrupt registers */
+#define AT_DMA_EBCIER          0x18                    /* Enable register */
+#define AT_DMA_EBCIDR          0x1c                    /* Disable register */
+#define AT_DMA_EBCIMR          0x20                    /* Mask Register */
+#define AT_DMA_EBCISR          0x24                    /* Status Register */
+#define AT_DMA_CBTC_OFFSET     8
+#define AT_DMA_ERR_OFFSET      16
+#define AT_DMA_BTC(x)          BIT((x))
+#define AT_DMA_CBTC(x)         BIT(AT_DMA_CBTC_OFFSET + (x))
+#define AT_DMA_ERR(x)          BIT(AT_DMA_ERR_OFFSET + (x))
+
+/* Channel Handler Enable Register */
+#define AT_DMA_CHER            0x28
+#define AT_DMA_ENA(x)          BIT((x))
+#define AT_DMA_SUSP(x)         BIT(8 + (x))
+#define AT_DMA_KEEP(x)         BIT(24 + (x))
+
+/* Channel Handler Disable Register */
+#define AT_DMA_CHDR            0x2c
+#define AT_DMA_DIS(x)          BIT(x)
+#define AT_DMA_RES(x)          BIT(8 + (x))
+
+/* Channel Handler Status Register */
+#define AT_DMA_CHSR            0x30
+#define AT_DMA_EMPT(x)         BIT(16 + (x))
+#define AT_DMA_STAL(x)         BIT(24 + (x))
+
+/* Channel registers base address */
+#define AT_DMA_CH_REGS_BASE    0x3c
+#define ch_regs(x)             (AT_DMA_CH_REGS_BASE + (x) * 0x28) /* Channel x base addr */
+
+/* Hardware register offset for each channel */
+#define ATC_SADDR_OFFSET       0x00    /* Source Address Register */
+#define ATC_DADDR_OFFSET       0x04    /* Destination Address Register */
+#define ATC_DSCR_OFFSET                0x08    /* Descriptor Address Register */
+#define ATC_CTRLA_OFFSET       0x0c    /* Control A Register */
+#define ATC_CTRLB_OFFSET       0x10    /* Control B Register */
+#define ATC_CFG_OFFSET         0x14    /* Configuration Register */
+#define ATC_SPIP_OFFSET                0x18    /* Src PIP Configuration Register */
+#define ATC_DPIP_OFFSET                0x1c    /* Dst PIP Configuration Register */
+
+
+/* Bitfield definitions */
+
+/* Bitfields in DSCR */
+#define ATC_DSCR_IF            GENMASK(1, 0)   /* Dsc feched via AHB-Lite Interface */
+
+/* Bitfields in CTRLA */
+#define ATC_BTSIZE_MAX         GENMASK(15, 0)  /* Maximum Buffer Transfer Size */
+#define ATC_BTSIZE             GENMASK(15, 0)  /* Buffer Transfer Size */
+#define ATC_SCSIZE             GENMASK(18, 16) /* Source Chunk Transfer Size */
+#define ATC_DCSIZE             GENMASK(22, 20) /* Destination Chunk Transfer Size */
+#define ATC_SRC_WIDTH          GENMASK(25, 24) /* Source Single Transfer Size */
+#define ATC_DST_WIDTH          GENMASK(29, 28) /* Destination Single Transfer Size */
+#define ATC_DONE               BIT(31) /* Tx Done (only written back in descriptor) */
+
+/* Bitfields in CTRLB */
+#define ATC_SIF                        GENMASK(1, 0)   /* Src tx done via AHB-Lite Interface i */
+#define ATC_DIF                        GENMASK(5, 4)   /* Dst tx done via AHB-Lite Interface i */
+#define AT_DMA_MEM_IF          0x0             /* interface 0 as memory interface */
+#define AT_DMA_PER_IF          0x1             /* interface 1 as peripheral interface */
+#define ATC_SRC_PIP            BIT(8)          /* Source Picture-in-Picture enabled */
+#define ATC_DST_PIP            BIT(12)         /* Destination Picture-in-Picture enabled */
+#define ATC_SRC_DSCR_DIS       BIT(16)         /* Src Descriptor fetch disable */
+#define ATC_DST_DSCR_DIS       BIT(20)         /* Dst Descriptor fetch disable */
+#define ATC_FC                 GENMASK(22, 21) /* Choose Flow Controller */
+#define ATC_FC_MEM2MEM         0x0             /* Mem-to-Mem (DMA) */
+#define ATC_FC_MEM2PER         0x1             /* Mem-to-Periph (DMA) */
+#define ATC_FC_PER2MEM         0x2             /* Periph-to-Mem (DMA) */
+#define ATC_FC_PER2PER         0x3             /* Periph-to-Periph (DMA) */
+#define ATC_FC_PER2MEM_PER     0x4             /* Periph-to-Mem (Peripheral) */
+#define ATC_FC_MEM2PER_PER     0x5             /* Mem-to-Periph (Peripheral) */
+#define ATC_FC_PER2PER_SRCPER  0x6             /* Periph-to-Periph (Src Peripheral) */
+#define ATC_FC_PER2PER_DSTPER  0x7             /* Periph-to-Periph (Dst Peripheral) */
+#define ATC_SRC_ADDR_MODE      GENMASK(25, 24)
+#define ATC_SRC_ADDR_MODE_INCR 0x0             /* Incrementing Mode */
+#define ATC_SRC_ADDR_MODE_DECR 0x1             /* Decrementing Mode */
+#define ATC_SRC_ADDR_MODE_FIXED        0x2             /* Fixed Mode */
+#define ATC_DST_ADDR_MODE      GENMASK(29, 28)
+#define ATC_DST_ADDR_MODE_INCR 0x0             /* Incrementing Mode */
+#define ATC_DST_ADDR_MODE_DECR 0x1             /* Decrementing Mode */
+#define ATC_DST_ADDR_MODE_FIXED        0x2             /* Fixed Mode */
+#define ATC_IEN                        BIT(30)         /* BTC interrupt enable (active low) */
+#define ATC_AUTO               BIT(31)         /* Auto multiple buffer tx enable */
+
+/* Bitfields in CFG */
+#define ATC_PER_MSB(h) ((0x30U & (h)) >> 4)    /* Extract most significant bits of a handshaking identifier */
+
+#define ATC_SRC_PER            GENMASK(3, 0)   /* Channel src rq associated with periph handshaking ifc h */
+#define ATC_DST_PER            GENMASK(7, 4)   /* Channel dst rq associated with periph handshaking ifc h */
+#define ATC_SRC_REP            BIT(8)          /* Source Replay Mod */
+#define ATC_SRC_H2SEL          BIT(9)          /* Source Handshaking Mod */
+#define ATC_SRC_PER_MSB                GENMASK(11, 10) /* Channel src rq (most significant bits) */
+#define ATC_DST_REP            BIT(12)         /* Destination Replay Mod */
+#define ATC_DST_H2SEL          BIT(13)         /* Destination Handshaking Mod */
+#define ATC_DST_PER_MSB                GENMASK(15, 14) /* Channel dst rq (most significant bits) */
+#define ATC_SOD                        BIT(16)         /* Stop On Done */
+#define ATC_LOCK_IF            BIT(20)         /* Interface Lock */
+#define ATC_LOCK_B             BIT(21)         /* AHB Bus Lock */
+#define ATC_LOCK_IF_L          BIT(22)         /* Master Interface Arbiter Lock */
+#define ATC_AHB_PROT           GENMASK(26, 24) /* AHB Protection */
+#define ATC_FIFOCFG            GENMASK(29, 28) /* FIFO Request Configuration */
+#define ATC_FIFOCFG_LARGESTBURST       0x0
+#define ATC_FIFOCFG_HALFFIFO           0x1
+#define ATC_FIFOCFG_ENOUGHSPACE                0x2
+
+/* Bitfields in SPIP */
+#define ATC_SPIP_HOLE          GENMASK(15, 0)
+#define ATC_SPIP_BOUNDARY      GENMASK(25, 16)
+
+/* Bitfields in DPIP */
+#define ATC_DPIP_HOLE          GENMASK(15, 0)
+#define ATC_DPIP_BOUNDARY      GENMASK(25, 16)
+
+#define ATC_SRC_PER_ID(id)     (FIELD_PREP(ATC_SRC_PER_MSB, (id)) |    \
+                                FIELD_PREP(ATC_SRC_PER, (id)))
+#define ATC_DST_PER_ID(id)     (FIELD_PREP(ATC_DST_PER_MSB, (id)) |    \
+                                FIELD_PREP(ATC_DST_PER, (id)))
+
+
+
+/*--  descriptors  -----------------------------------------------------*/
+
+/* LLI == Linked List Item; aka DMA buffer descriptor */
+struct at_lli {
+       /* values that are not changed by hardware */
+       u32 saddr;
+       u32 daddr;
+       /* value that may get written back: */
+       u32 ctrla;
+       /* more values that are not changed by hardware */
+       u32 ctrlb;
+       u32 dscr;       /* chain to next lli */
+};
+
+/**
+ * struct atdma_sg - atdma scatter gather entry
+ * @len: length of the current Linked List Item.
+ * @lli: linked list item that is passed to the DMA controller
+ * @lli_phys: physical address of the LLI.
+ */
+struct atdma_sg {
+       unsigned int len;
+       struct at_lli *lli;
+       dma_addr_t lli_phys;
+};
+
+/**
+ * struct at_desc - software descriptor
+ * @vd: pointer to the virtual dma descriptor.
+ * @atchan: pointer to the atmel dma channel.
+ * @total_len: total transaction byte count
+ * @sg_len: number of sg entries.
+ * @sg: array of sgs.
+ */
+struct at_desc {
+       struct                          virt_dma_desc vd;
+       struct                          at_dma_chan *atchan;
+       size_t                          total_len;
+       unsigned int                    sglen;
+       /* Interleaved data */
+       size_t                          boundary;
+       size_t                          dst_hole;
+       size_t                          src_hole;
+
+       /* Memset temporary buffer */
+       bool                            memset_buffer;
+       dma_addr_t                      memset_paddr;
+       int                             *memset_vaddr;
+       struct atdma_sg                 sg[];
+};
+
+/*--  Channels  --------------------------------------------------------*/
+
+/**
+ * atc_status - information bits stored in channel status flag
+ *
+ * Manipulated with atomic operations.
+ */
+enum atc_status {
+       ATC_IS_PAUSED = 1,
+       ATC_IS_CYCLIC = 24,
+};
+
+/**
+ * struct at_dma_chan - internal representation of an Atmel HDMAC channel
+ * @vc: virtual dma channel entry.
+ * @atdma: pointer to the driver data.
+ * @ch_regs: memory mapped register base
+ * @mask: channel index in a mask
+ * @per_if: peripheral interface
+ * @mem_if: memory interface
+ * @status: transmit status information from irq/prep* functions
+ *                to tasklet (use atomic operations)
+ * @save_cfg: configuration register that is saved on suspend/resume cycle
+ * @save_dscr: for cyclic operations, preserve next descriptor address in
+ *             the cyclic list on suspend/resume cycle
+ * @dma_sconfig: configuration for slave transfers, passed via
+ * .device_config
+ * @desc: pointer to the atmel dma descriptor.
+ */
+struct at_dma_chan {
+       struct virt_dma_chan    vc;
+       struct at_dma           *atdma;
+       void __iomem            *ch_regs;
+       u8                      mask;
+       u8                      per_if;
+       u8                      mem_if;
+       unsigned long           status;
+       u32                     save_cfg;
+       u32                     save_dscr;
+       struct dma_slave_config dma_sconfig;
+       bool                    cyclic;
+       struct at_desc          *desc;
+};
+
+#define        channel_readl(atchan, name) \
+       __raw_readl((atchan)->ch_regs + ATC_##name##_OFFSET)
+
+#define        channel_writel(atchan, name, val) \
+       __raw_writel((val), (atchan)->ch_regs + ATC_##name##_OFFSET)
+
+/*
+ * Fix sconfig's burst size according to at_hdmac. We need to convert them as:
+ * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3, 32 -> 4, 64 -> 5, 128 -> 6, 256 -> 7.
+ *
+ * This can be done by finding most significant bit set.
+ */
+static inline void convert_burst(u32 *maxburst)
+{
+       if (*maxburst > 1)
+               *maxburst = fls(*maxburst) - 2;
+       else
+               *maxburst = 0;
+}
+
+/*
+ * Fix sconfig's bus width according to at_hdmac.
+ * 1 byte -> 0, 2 bytes -> 1, 4 bytes -> 2.
+ */
+static inline u8 convert_buswidth(enum dma_slave_buswidth addr_width)
+{
+       switch (addr_width) {
+       case DMA_SLAVE_BUSWIDTH_2_BYTES:
+               return 1;
+       case DMA_SLAVE_BUSWIDTH_4_BYTES:
+               return 2;
+       default:
+               /* For 1 byte width or fallback */
+               return 0;
+       }
+}
+
+/*--  Controller  ------------------------------------------------------*/
+
+/**
+ * struct at_dma - internal representation of an Atmel HDMA Controller
+ * @dma_device: dmaengine dma_device object members
+ * @atdma_devtype: identifier of DMA controller compatibility
+ * @ch_regs: memory mapped register base
+ * @clk: dma controller clock
+ * @save_imr: interrupt mask register that is saved on suspend/resume cycle
+ * @all_chan_mask: all channels availlable in a mask
+ * @lli_pool: hw lli table
+ * @chan: channels table to store at_dma_chan structures
+ */
+struct at_dma {
+       struct dma_device       dma_device;
+       void __iomem            *regs;
+       struct clk              *clk;
+       u32                     save_imr;
+
+       u8                      all_chan_mask;
+
+       struct dma_pool         *lli_pool;
+       struct dma_pool         *memset_pool;
+       /* AT THE END channels table */
+       struct at_dma_chan      chan[];
+};
+
+#define        dma_readl(atdma, name) \
+       __raw_readl((atdma)->regs + AT_DMA_##name)
+#define        dma_writel(atdma, name, val) \
+       __raw_writel((val), (atdma)->regs + AT_DMA_##name)
+
+static inline struct at_desc *to_atdma_desc(struct dma_async_tx_descriptor *t)
+{
+       return container_of(t, struct at_desc, vd.tx);
+}
+
+static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *chan)
+{
+       return container_of(chan, struct at_dma_chan, vc.chan);
+}
+
+static inline struct at_dma *to_at_dma(struct dma_device *ddev)
+{
+       return container_of(ddev, struct at_dma, dma_device);
+}
+
+
+/*--  Helper functions  ------------------------------------------------*/
+
+static struct device *chan2dev(struct dma_chan *chan)
+{
+       return &chan->dev->device;
+}
+
+#if defined(VERBOSE_DEBUG)
+static void vdbg_dump_regs(struct at_dma_chan *atchan)
+{
+       struct at_dma   *atdma = to_at_dma(atchan->vc.chan.device);
+
+       dev_err(chan2dev(&atchan->vc.chan),
+               "  channel %d : imr = 0x%x, chsr = 0x%x\n",
+               atchan->vc.chan.chan_id,
+               dma_readl(atdma, EBCIMR),
+               dma_readl(atdma, CHSR));
+
+       dev_err(chan2dev(&atchan->vc.chan),
+               "  channel: s0x%x d0x%x ctrl0x%x:0x%x cfg0x%x l0x%x\n",
+               channel_readl(atchan, SADDR),
+               channel_readl(atchan, DADDR),
+               channel_readl(atchan, CTRLA),
+               channel_readl(atchan, CTRLB),
+               channel_readl(atchan, CFG),
+               channel_readl(atchan, DSCR));
+}
+#else
+static void vdbg_dump_regs(struct at_dma_chan *atchan) {}
+#endif
+
+static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
+{
+       dev_crit(chan2dev(&atchan->vc.chan),
+                "desc: s%pad d%pad ctrl0x%x:0x%x l%pad\n",
+                &lli->saddr, &lli->daddr,
+                lli->ctrla, lli->ctrlb, &lli->dscr);
+}
+
+
+static void atc_setup_irq(struct at_dma *atdma, int chan_id, int on)
+{
+       u32 ebci;
+
+       /* enable interrupts on buffer transfer completion & error */
+       ebci =    AT_DMA_BTC(chan_id)
+               | AT_DMA_ERR(chan_id);
+       if (on)
+               dma_writel(atdma, EBCIER, ebci);
+       else
+               dma_writel(atdma, EBCIDR, ebci);
+}
+
+static void atc_enable_chan_irq(struct at_dma *atdma, int chan_id)
+{
+       atc_setup_irq(atdma, chan_id, 1);
+}
+
+static void atc_disable_chan_irq(struct at_dma *atdma, int chan_id)
+{
+       atc_setup_irq(atdma, chan_id, 0);
+}
+
+
+/**
+ * atc_chan_is_enabled - test if given channel is enabled
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_enabled(struct at_dma_chan *atchan)
+{
+       struct at_dma *atdma = to_at_dma(atchan->vc.chan.device);
+
+       return !!(dma_readl(atdma, CHSR) & atchan->mask);
+}
+
+/**
+ * atc_chan_is_paused - test channel pause/resume status
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_paused(struct at_dma_chan *atchan)
+{
+       return test_bit(ATC_IS_PAUSED, &atchan->status);
+}
+
+/**
+ * atc_chan_is_cyclic - test if given channel has cyclic property set
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_cyclic(struct at_dma_chan *atchan)
+{
+       return test_bit(ATC_IS_CYCLIC, &atchan->status);
+}
+
+/**
+ * set_lli_eol - set end-of-link to descriptor so it will end transfer
+ * @desc: descriptor, signle or at the end of a chain, to end chain on
+ * @i: index of the atmel scatter gather entry that is at the end of the chain.
+ */
+static void set_lli_eol(struct at_desc *desc, unsigned int i)
+{
+       u32 ctrlb = desc->sg[i].lli->ctrlb;
+
+       ctrlb &= ~ATC_IEN;
+       ctrlb |= ATC_SRC_DSCR_DIS | ATC_DST_DSCR_DIS;
+
+       desc->sg[i].lli->ctrlb = ctrlb;
+       desc->sg[i].lli->dscr = 0;
+}
+
+#define        ATC_DEFAULT_CFG         FIELD_PREP(ATC_FIFOCFG, ATC_FIFOCFG_HALFFIFO)
+#define        ATC_DEFAULT_CTRLB       (FIELD_PREP(ATC_SIF, AT_DMA_MEM_IF) | \
+                                FIELD_PREP(ATC_DIF, AT_DMA_MEM_IF))
 #define ATC_DMA_BUSWIDTHS\
        (BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\
        BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |\
@@ -74,13 +517,6 @@ struct at_dma_slave {
        u32                     cfg;
 };
 
-/* prototypes */
-static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx);
-static void atc_issue_pending(struct dma_chan *chan);
-
-
-/*----------------------------------------------------------------------*/
-
 static inline unsigned int atc_get_xfer_width(dma_addr_t src, dma_addr_t dst,
                                                size_t len)
 {
@@ -96,194 +532,72 @@ static inline unsigned int atc_get_xfer_width(dma_addr_t src, dma_addr_t dst,
        return width;
 }
 
-static struct at_desc *atc_first_active(struct at_dma_chan *atchan)
-{
-       return list_first_entry(&atchan->active_list,
-                               struct at_desc, desc_node);
-}
-
-static struct at_desc *atc_first_queued(struct at_dma_chan *atchan)
-{
-       return list_first_entry(&atchan->queue,
-                               struct at_desc, desc_node);
-}
-
-/**
- * atc_alloc_descriptor - allocate and return an initialized descriptor
- * @chan: the channel to allocate descriptors for
- * @gfp_flags: GFP allocation flags
- *
- * Note: The ack-bit is positioned in the descriptor flag at creation time
- *       to make initial allocation more convenient. This bit will be cleared
- *       and control will be given to client at usage time (during
- *       preparation functions).
- */
-static struct at_desc *atc_alloc_descriptor(struct dma_chan *chan,
-                                           gfp_t gfp_flags)
-{
-       struct at_desc  *desc = NULL;
-       struct at_dma   *atdma = to_at_dma(chan->device);
-       dma_addr_t phys;
-
-       desc = dma_pool_zalloc(atdma->dma_desc_pool, gfp_flags, &phys);
-       if (desc) {
-               INIT_LIST_HEAD(&desc->tx_list);
-               dma_async_tx_descriptor_init(&desc->txd, chan);
-               /* txd.flags will be overwritten in prep functions */
-               desc->txd.flags = DMA_CTRL_ACK;
-               desc->txd.tx_submit = atc_tx_submit;
-               desc->txd.phys = phys;
-       }
-
-       return desc;
-}
-
-/**
- * atc_desc_get - get an unused descriptor from free_list
- * @atchan: channel we want a new descriptor for
- */
-static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
+static void atdma_lli_chain(struct at_desc *desc, unsigned int i)
 {
-       struct at_desc *desc, *_desc;
-       struct at_desc *ret = NULL;
-       unsigned long flags;
-       unsigned int i = 0;
-
-       spin_lock_irqsave(&atchan->lock, flags);
-       list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) {
-               i++;
-               if (async_tx_test_ack(&desc->txd)) {
-                       list_del(&desc->desc_node);
-                       ret = desc;
-                       break;
-               }
-               dev_dbg(chan2dev(&atchan->chan_common),
-                               "desc %p not ACKed\n", desc);
-       }
-       spin_unlock_irqrestore(&atchan->lock, flags);
-       dev_vdbg(chan2dev(&atchan->chan_common),
-               "scanned %u descriptors on freelist\n", i);
-
-       /* no more descriptor available in initial pool: create one more */
-       if (!ret)
-               ret = atc_alloc_descriptor(&atchan->chan_common, GFP_NOWAIT);
-
-       return ret;
-}
+       struct atdma_sg *atdma_sg = &desc->sg[i];
 
-/**
- * atc_desc_put - move a descriptor, including any children, to the free list
- * @atchan: channel we work on
- * @desc: descriptor, at the head of a chain, to move to free list
- */
-static void atc_desc_put(struct at_dma_chan *atchan, struct at_desc *desc)
-{
-       if (desc) {
-               struct at_desc *child;
-               unsigned long flags;
-
-               spin_lock_irqsave(&atchan->lock, flags);
-               list_for_each_entry(child, &desc->tx_list, desc_node)
-                       dev_vdbg(chan2dev(&atchan->chan_common),
-                                       "moving child desc %p to freelist\n",
-                                       child);
-               list_splice_init(&desc->tx_list, &atchan->free_list);
-               dev_vdbg(chan2dev(&atchan->chan_common),
-                        "moving desc %p to freelist\n", desc);
-               list_add(&desc->desc_node, &atchan->free_list);
-               spin_unlock_irqrestore(&atchan->lock, flags);
-       }
-}
-
-/**
- * atc_desc_chain - build chain adding a descriptor
- * @first: address of first descriptor of the chain
- * @prev: address of previous descriptor of the chain
- * @desc: descriptor to queue
- *
- * Called from prep_* functions
- */
-static void atc_desc_chain(struct at_desc **first, struct at_desc **prev,
-                          struct at_desc *desc)
-{
-       if (!(*first)) {
-               *first = desc;
-       } else {
-               /* inform the HW lli about chaining */
-               (*prev)->lli.dscr = desc->txd.phys;
-               /* insert the link descriptor to the LD ring */
-               list_add_tail(&desc->desc_node,
-                               &(*first)->tx_list);
-       }
-       *prev = desc;
+       if (i)
+               desc->sg[i - 1].lli->dscr = atdma_sg->lli_phys;
 }
 
 /**
  * atc_dostart - starts the DMA engine for real
  * @atchan: the channel we want to start
- * @first: first descriptor in the list we want to begin with
- *
- * Called with atchan->lock held and bh disabled
  */
-static void atc_dostart(struct at_dma_chan *atchan, struct at_desc *first)
+static void atc_dostart(struct at_dma_chan *atchan)
 {
-       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
+       struct virt_dma_desc *vd = vchan_next_desc(&atchan->vc);
+       struct at_desc *desc;
 
-       /* ASSERT:  channel is idle */
-       if (atc_chan_is_enabled(atchan)) {
-               dev_err(chan2dev(&atchan->chan_common),
-                       "BUG: Attempted to start non-idle channel\n");
-               dev_err(chan2dev(&atchan->chan_common),
-                       "  channel: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n",
-                       channel_readl(atchan, SADDR),
-                       channel_readl(atchan, DADDR),
-                       channel_readl(atchan, CTRLA),
-                       channel_readl(atchan, CTRLB),
-                       channel_readl(atchan, DSCR));
-
-               /* The tasklet will hopefully advance the queue... */
+       if (!vd) {
+               atchan->desc = NULL;
                return;
        }
 
        vdbg_dump_regs(atchan);
 
+       list_del(&vd->node);
+       atchan->desc = desc = to_atdma_desc(&vd->tx);
+
        channel_writel(atchan, SADDR, 0);
        channel_writel(atchan, DADDR, 0);
        channel_writel(atchan, CTRLA, 0);
        channel_writel(atchan, CTRLB, 0);
-       channel_writel(atchan, DSCR, first->txd.phys);
-       channel_writel(atchan, SPIP, ATC_SPIP_HOLE(first->src_hole) |
-                      ATC_SPIP_BOUNDARY(first->boundary));
-       channel_writel(atchan, DPIP, ATC_DPIP_HOLE(first->dst_hole) |
-                      ATC_DPIP_BOUNDARY(first->boundary));
+       channel_writel(atchan, DSCR, desc->sg[0].lli_phys);
+       channel_writel(atchan, SPIP,
+                      FIELD_PREP(ATC_SPIP_HOLE, desc->src_hole) |
+                      FIELD_PREP(ATC_SPIP_BOUNDARY, desc->boundary));
+       channel_writel(atchan, DPIP,
+                      FIELD_PREP(ATC_DPIP_HOLE, desc->dst_hole) |
+                      FIELD_PREP(ATC_DPIP_BOUNDARY, desc->boundary));
+
        /* Don't allow CPU to reorder channel enable. */
        wmb();
-       dma_writel(atdma, CHER, atchan->mask);
+       dma_writel(atchan->atdma, CHER, atchan->mask);
 
        vdbg_dump_regs(atchan);
 }
 
-/*
- * atc_get_desc_by_cookie - get the descriptor of a cookie
- * @atchan: the DMA channel
- * @cookie: the cookie to get the descriptor for
- */
-static struct at_desc *atc_get_desc_by_cookie(struct at_dma_chan *atchan,
-                                               dma_cookie_t cookie)
+static void atdma_desc_free(struct virt_dma_desc *vd)
 {
-       struct at_desc *desc, *_desc;
+       struct at_dma *atdma = to_at_dma(vd->tx.chan->device);
+       struct at_desc *desc = to_atdma_desc(&vd->tx);
+       unsigned int i;
 
-       list_for_each_entry_safe(desc, _desc, &atchan->queue, desc_node) {
-               if (desc->txd.cookie == cookie)
-                       return desc;
+       for (i = 0; i < desc->sglen; i++) {
+               if (desc->sg[i].lli)
+                       dma_pool_free(atdma->lli_pool, desc->sg[i].lli,
+                                     desc->sg[i].lli_phys);
        }
 
-       list_for_each_entry_safe(desc, _desc, &atchan->active_list, desc_node) {
-               if (desc->txd.cookie == cookie)
-                       return desc;
+       /* If the transfer was a memset, free our temporary buffer */
+       if (desc->memset_buffer) {
+               dma_pool_free(atdma->memset_pool, desc->memset_vaddr,
+                             desc->memset_paddr);
+               desc->memset_buffer = false;
        }
 
-       return NULL;
+       kfree(desc);
 }
 
 /**
@@ -293,10 +607,10 @@ static struct at_desc *atc_get_desc_by_cookie(struct at_dma_chan *atchan,
  * @current_len: the number of bytes left before reading CTRLA
  * @ctrla: the value of CTRLA
  */
-static inline int atc_calc_bytes_left(int current_len, u32 ctrla)
+static inline u32 atc_calc_bytes_left(u32 current_len, u32 ctrla)
 {
-       u32 btsize = (ctrla & ATC_BTSIZE_MAX);
-       u32 src_width = ATC_REG_TO_SRC_WIDTH(ctrla);
+       u32 btsize = FIELD_GET(ATC_BTSIZE, ctrla);
+       u32 src_width = FIELD_GET(ATC_SRC_WIDTH, ctrla);
 
        /*
         * According to the datasheet, when reading the Control A Register
@@ -308,246 +622,153 @@ static inline int atc_calc_bytes_left(int current_len, u32 ctrla)
 }
 
 /**
- * atc_get_bytes_left - get the number of bytes residue for a cookie
- * @chan: DMA channel
- * @cookie: transaction identifier to check status of
+ * atc_get_llis_residue - Get residue for a hardware linked list transfer
+ *
+ * Calculate the residue by removing the length of the Linked List Item (LLI)
+ * already transferred from the total length. To get the current LLI we can use
+ * the value of the channel's DSCR register and compare it against the DSCR
+ * value of each LLI.
+ *
+ * The CTRLA register provides us with the amount of data already read from the
+ * source for the LLI. So we can compute a more accurate residue by also
+ * removing the number of bytes corresponding to this amount of data.
+ *
+ * However, the DSCR and CTRLA registers cannot be read both atomically. Hence a
+ * race condition may occur: the first read register may refer to one LLI
+ * whereas the second read may refer to a later LLI in the list because of the
+ * DMA transfer progression inbetween the two reads.
+ *
+ * One solution could have been to pause the DMA transfer, read the DSCR and
+ * CTRLA then resume the DMA transfer. Nonetheless, this approach presents some
+ * drawbacks:
+ * - If the DMA transfer is paused, RX overruns or TX underruns are more likey
+ *   to occur depending on the system latency. Taking the USART driver as an
+ *   example, it uses a cyclic DMA transfer to read data from the Receive
+ *   Holding Register (RHR) to avoid RX overruns since the RHR is not protected
+ *   by any FIFO on most Atmel SoCs. So pausing the DMA transfer to compute the
+ *   residue would break the USART driver design.
+ * - The atc_pause() function masks interrupts but we'd rather avoid to do so
+ * for system latency purpose.
+ *
+ * Then we'd rather use another solution: the DSCR is read a first time, the
+ * CTRLA is read in turn, next the DSCR is read a second time. If the two
+ * consecutive read values of the DSCR are the same then we assume both refers
+ * to the very same LLI as well as the CTRLA value read inbetween does. For
+ * cyclic tranfers, the assumption is that a full loop is "not so fast". If the
+ * two DSCR values are different, we read again the CTRLA then the DSCR till two
+ * consecutive read values from DSCR are equal or till the maximum trials is
+ * reach. This algorithm is very unlikely not to find a stable value for DSCR.
+ * @atchan: pointer to an atmel hdmac channel.
+ * @desc: pointer to the descriptor for which the residue is calculated.
+ * @residue: residue to be set to dma_tx_state.
+ * Returns 0 on success, -errno otherwise.
  */
-static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie)
+static int atc_get_llis_residue(struct at_dma_chan *atchan,
+                               struct at_desc *desc, u32 *residue)
 {
-       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
-       struct at_desc *desc_first = atc_first_active(atchan);
-       struct at_desc *desc;
-       int ret;
-       u32 ctrla, dscr;
+       u32 len, ctrla, dscr;
        unsigned int i;
 
-       /*
-        * If the cookie doesn't match to the currently running transfer then
-        * we can return the total length of the associated DMA transfer,
-        * because it is still queued.
-        */
-       desc = atc_get_desc_by_cookie(atchan, cookie);
-       if (desc == NULL)
-               return -EINVAL;
-       else if (desc != desc_first)
-               return desc->total_len;
+       len = desc->total_len;
+       dscr = channel_readl(atchan, DSCR);
+       rmb(); /* ensure DSCR is read before CTRLA */
+       ctrla = channel_readl(atchan, CTRLA);
+       for (i = 0; i < ATC_MAX_DSCR_TRIALS; ++i) {
+               u32 new_dscr;
 
-       /* cookie matches to the currently running transfer */
-       ret = desc_first->total_len;
-
-       if (desc_first->lli.dscr) {
-               /* hardware linked list transfer */
+               rmb(); /* ensure DSCR is read after CTRLA */
+               new_dscr = channel_readl(atchan, DSCR);
 
                /*
-                * Calculate the residue by removing the length of the child
-                * descriptors already transferred from the total length.
-                * To get the current child descriptor we can use the value of
-                * the channel's DSCR register and compare it against the value
-                * of the hardware linked list structure of each child
-                * descriptor.
-                *
-                * The CTRLA register provides us with the amount of data
-                * already read from the source for the current child
-                * descriptor. So we can compute a more accurate residue by also
-                * removing the number of bytes corresponding to this amount of
-                * data.
-                *
-                * However, the DSCR and CTRLA registers cannot be read both
-                * atomically. Hence a race condition may occur: the first read
-                * register may refer to one child descriptor whereas the second
-                * read may refer to a later child descriptor in the list
-                * because of the DMA transfer progression inbetween the two
-                * reads.
-                *
-                * One solution could have been to pause the DMA transfer, read
-                * the DSCR and CTRLA then resume the DMA transfer. Nonetheless,
-                * this approach presents some drawbacks:
-                * - If the DMA transfer is paused, RX overruns or TX underruns
-                *   are more likey to occur depending on the system latency.
-                *   Taking the USART driver as an example, it uses a cyclic DMA
-                *   transfer to read data from the Receive Holding Register
-                *   (RHR) to avoid RX overruns since the RHR is not protected
-                *   by any FIFO on most Atmel SoCs. So pausing the DMA transfer
-                *   to compute the residue would break the USART driver design.
-                * - The atc_pause() function masks interrupts but we'd rather
-                *   avoid to do so for system latency purpose.
-                *
-                * Then we'd rather use another solution: the DSCR is read a
-                * first time, the CTRLA is read in turn, next the DSCR is read
-                * a second time. If the two consecutive read values of the DSCR
-                * are the same then we assume both refers to the very same
-                * child descriptor as well as the CTRLA value read inbetween
-                * does. For cyclic tranfers, the assumption is that a full loop
-                * is "not so fast".
-                * If the two DSCR values are different, we read again the CTRLA
-                * then the DSCR till two consecutive read values from DSCR are
-                * equal or till the maxium trials is reach.
-                * This algorithm is very unlikely not to find a stable value for
-                * DSCR.
+                * If the DSCR register value has not changed inside the DMA
+                * controller since the previous read, we assume that both the
+                * dscr and ctrla values refers to the very same descriptor.
                 */
-
-               dscr = channel_readl(atchan, DSCR);
-               rmb(); /* ensure DSCR is read before CTRLA */
-               ctrla = channel_readl(atchan, CTRLA);
-               for (i = 0; i < ATC_MAX_DSCR_TRIALS; ++i) {
-                       u32 new_dscr;
-
-                       rmb(); /* ensure DSCR is read after CTRLA */
-                       new_dscr = channel_readl(atchan, DSCR);
-
-                       /*
-                        * If the DSCR register value has not changed inside the
-                        * DMA controller since the previous read, we assume
-                        * that both the dscr and ctrla values refers to the
-                        * very same descriptor.
-                        */
-                       if (likely(new_dscr == dscr))
-                               break;
-
-                       /*
-                        * DSCR has changed inside the DMA controller, so the
-                        * previouly read value of CTRLA may refer to an already
-                        * processed descriptor hence could be outdated.
-                        * We need to update ctrla to match the current
-                        * descriptor.
-                        */
-                       dscr = new_dscr;
-                       rmb(); /* ensure DSCR is read before CTRLA */
-                       ctrla = channel_readl(atchan, CTRLA);
-               }
-               if (unlikely(i == ATC_MAX_DSCR_TRIALS))
-                       return -ETIMEDOUT;
-
-               /* for the first descriptor we can be more accurate */
-               if (desc_first->lli.dscr == dscr)
-                       return atc_calc_bytes_left(ret, ctrla);
-
-               ret -= desc_first->len;
-               list_for_each_entry(desc, &desc_first->tx_list, desc_node) {
-                       if (desc->lli.dscr == dscr)
-                               break;
-
-                       ret -= desc->len;
-               }
+               if (likely(new_dscr == dscr))
+                       break;
 
                /*
-                * For the current descriptor in the chain we can calculate
-                * the remaining bytes using the channel's register.
+                * DSCR has changed inside the DMA controller, so the previouly
+                * read value of CTRLA may refer to an already processed
+                * descriptor hence could be outdated. We need to update ctrla
+                * to match the current descriptor.
                 */
-               ret = atc_calc_bytes_left(ret, ctrla);
-       } else {
-               /* single transfer */
+               dscr = new_dscr;
+               rmb(); /* ensure DSCR is read before CTRLA */
                ctrla = channel_readl(atchan, CTRLA);
-               ret = atc_calc_bytes_left(ret, ctrla);
        }
+       if (unlikely(i == ATC_MAX_DSCR_TRIALS))
+               return -ETIMEDOUT;
 
-       return ret;
-}
-
-/**
- * atc_chain_complete - finish work for one transaction chain
- * @atchan: channel we work on
- * @desc: descriptor at the head of the chain we want do complete
- */
-static void
-atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
-{
-       struct dma_async_tx_descriptor  *txd = &desc->txd;
-       struct at_dma                   *atdma = to_at_dma(atchan->chan_common.device);
-       unsigned long flags;
-
-       dev_vdbg(chan2dev(&atchan->chan_common),
-               "descriptor %u complete\n", txd->cookie);
-
-       spin_lock_irqsave(&atchan->lock, flags);
-
-       /* mark the descriptor as complete for non cyclic cases only */
-       if (!atc_chan_is_cyclic(atchan))
-               dma_cookie_complete(txd);
-
-       spin_unlock_irqrestore(&atchan->lock, flags);
-
-       dma_descriptor_unmap(txd);
-       /* for cyclic transfers,
-        * no need to replay callback function while stopping */
-       if (!atc_chan_is_cyclic(atchan))
-               dmaengine_desc_get_callback_invoke(txd, NULL);
+       /* For the first descriptor we can be more accurate. */
+       if (desc->sg[0].lli->dscr == dscr) {
+               *residue = atc_calc_bytes_left(len, ctrla);
+               return 0;
+       }
+       len -= desc->sg[0].len;
 
-       dma_run_dependencies(txd);
+       for (i = 1; i < desc->sglen; i++) {
+               if (desc->sg[i].lli && desc->sg[i].lli->dscr == dscr)
+                       break;
+               len -= desc->sg[i].len;
+       }
 
-       spin_lock_irqsave(&atchan->lock, flags);
-       /* move children to free_list */
-       list_splice_init(&desc->tx_list, &atchan->free_list);
-       /* add myself to free_list */
-       list_add(&desc->desc_node, &atchan->free_list);
-       spin_unlock_irqrestore(&atchan->lock, flags);
+       /*
+        * For the current LLI in the chain we can calculate the remaining bytes
+        * using the channel's CTRLA register.
+        */
+       *residue = atc_calc_bytes_left(len, ctrla);
+       return 0;
 
-       /* If the transfer was a memset, free our temporary buffer */
-       if (desc->memset_buffer) {
-               dma_pool_free(atdma->memset_pool, desc->memset_vaddr,
-                             desc->memset_paddr);
-               desc->memset_buffer = false;
-       }
 }
 
 /**
- * atc_advance_work - at the end of a transaction, move forward
- * @atchan: channel where the transaction ended
+ * atc_get_residue - get the number of bytes residue for a cookie.
+ * The residue is passed by address and updated on success.
+ * @chan: DMA channel
+ * @cookie: transaction identifier to check status of
+ * @residue: residue to be updated.
+ * Return 0 on success, -errono otherwise.
  */
-static void atc_advance_work(struct at_dma_chan *atchan)
+static int atc_get_residue(struct dma_chan *chan, dma_cookie_t cookie,
+                          u32 *residue)
 {
-       struct at_desc *desc;
-       unsigned long flags;
+       struct at_dma_chan *atchan = to_at_dma_chan(chan);
+       struct virt_dma_desc *vd;
+       struct at_desc *desc = NULL;
+       u32 len, ctrla;
 
-       dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n");
+       vd = vchan_find_desc(&atchan->vc, cookie);
+       if (vd)
+               desc = to_atdma_desc(&vd->tx);
+       else if (atchan->desc && atchan->desc->vd.tx.cookie == cookie)
+               desc = atchan->desc;
 
-       spin_lock_irqsave(&atchan->lock, flags);
-       if (atc_chan_is_enabled(atchan) || list_empty(&atchan->active_list))
-               return spin_unlock_irqrestore(&atchan->lock, flags);
+       if (!desc)
+               return -EINVAL;
 
-       desc = atc_first_active(atchan);
-       /* Remove the transfer node from the active list. */
-       list_del_init(&desc->desc_node);
-       spin_unlock_irqrestore(&atchan->lock, flags);
-       atc_chain_complete(atchan, desc);
+       if (desc->sg[0].lli->dscr)
+               /* hardware linked list transfer */
+               return atc_get_llis_residue(atchan, desc, residue);
 
-       /* advance work */
-       spin_lock_irqsave(&atchan->lock, flags);
-       if (!list_empty(&atchan->active_list)) {
-               desc = atc_first_queued(atchan);
-               list_move_tail(&desc->desc_node, &atchan->active_list);
-               atc_dostart(atchan, desc);
-       }
-       spin_unlock_irqrestore(&atchan->lock, flags);
+       /* single transfer */
+       len = desc->total_len;
+       ctrla = channel_readl(atchan, CTRLA);
+       *residue = atc_calc_bytes_left(len, ctrla);
+       return 0;
 }
 
-
 /**
  * atc_handle_error - handle errors reported by DMA controller
- * @atchan: channel where error occurs
+ * @atchan: channel where error occurs.
+ * @i: channel index
  */
-static void atc_handle_error(struct at_dma_chan *atchan)
+static void atc_handle_error(struct at_dma_chan *atchan, unsigned int i)
 {
-       struct at_desc *bad_desc;
-       struct at_desc *desc;
-       struct at_desc *child;
-       unsigned long flags;
+       struct at_desc *desc = atchan->desc;
 
-       spin_lock_irqsave(&atchan->lock, flags);
-       /*
-        * The descriptor currently at the head of the active list is
-        * broked. Since we don't have any way to report errors, we'll
-        * just have to scream loudly and try to carry on.
-        */
-       bad_desc = atc_first_active(atchan);
-       list_del_init(&bad_desc->desc_node);
-
-       /* Try to restart the controller */
-       if (!list_empty(&atchan->active_list)) {
-               desc = atc_first_queued(atchan);
-               list_move_tail(&desc->desc_node, &atchan->active_list);
-               atc_dostart(atchan, desc);
-       }
+       /* Disable channel on AHB error */
+       dma_writel(atchan->atdma, CHDR, AT_DMA_RES(i) | atchan->mask);
 
        /*
         * KERN_CRITICAL may seem harsh, but since this only happens
@@ -556,54 +777,42 @@ static void atc_handle_error(struct at_dma_chan *atchan)
         * controller flagged an error instead of scribbling over
         * random memory locations.
         */
-       dev_crit(chan2dev(&atchan->chan_common),
-                       "Bad descriptor submitted for DMA!\n");
-       dev_crit(chan2dev(&atchan->chan_common),
-                       "  cookie: %d\n", bad_desc->txd.cookie);
-       atc_dump_lli(atchan, &bad_desc->lli);
-       list_for_each_entry(child, &bad_desc->tx_list, desc_node)
-               atc_dump_lli(atchan, &child->lli);
-
-       spin_unlock_irqrestore(&atchan->lock, flags);
-
-       /* Pretend the descriptor completed successfully */
-       atc_chain_complete(atchan, bad_desc);
+       dev_crit(chan2dev(&atchan->vc.chan), "Bad descriptor submitted for DMA!\n");
+       dev_crit(chan2dev(&atchan->vc.chan), "cookie: %d\n",
+                desc->vd.tx.cookie);
+       for (i = 0; i < desc->sglen; i++)
+               atc_dump_lli(atchan, desc->sg[i].lli);
 }
 
-/**
- * atc_handle_cyclic - at the end of a period, run callback function
- * @atchan: channel used for cyclic operations
- */
-static void atc_handle_cyclic(struct at_dma_chan *atchan)
+static void atdma_handle_chan_done(struct at_dma_chan *atchan, u32 pending,
+                                  unsigned int i)
 {
-       struct at_desc                  *first = atc_first_active(atchan);
-       struct dma_async_tx_descriptor  *txd = &first->txd;
-
-       dev_vdbg(chan2dev(&atchan->chan_common),
-                       "new cyclic period llp 0x%08x\n",
-                       channel_readl(atchan, DSCR));
-
-       dmaengine_desc_get_callback_invoke(txd, NULL);
-}
-
-/*--  IRQ & Tasklet  ---------------------------------------------------*/
-
-static void atc_tasklet(struct tasklet_struct *t)
-{
-       struct at_dma_chan *atchan = from_tasklet(atchan, t, tasklet);
+       struct at_desc *desc;
 
-       if (test_and_clear_bit(ATC_IS_ERROR, &atchan->status))
-               return atc_handle_error(atchan);
+       spin_lock(&atchan->vc.lock);
+       desc = atchan->desc;
 
-       if (atc_chan_is_cyclic(atchan))
-               return atc_handle_cyclic(atchan);
+       if (desc) {
+               if (pending & AT_DMA_ERR(i)) {
+                       atc_handle_error(atchan, i);
+                       /* Pretend the descriptor completed successfully */
+               }
 
-       atc_advance_work(atchan);
+               if (atc_chan_is_cyclic(atchan)) {
+                       vchan_cyclic_callback(&desc->vd);
+               } else {
+                       vchan_cookie_complete(&desc->vd);
+                       atchan->desc = NULL;
+                       if (!(atc_chan_is_enabled(atchan)))
+                               atc_dostart(atchan);
+               }
+       }
+       spin_unlock(&atchan->vc.lock);
 }
 
 static irqreturn_t at_dma_interrupt(int irq, void *dev_id)
 {
-       struct at_dma           *atdma = (struct at_dma *)dev_id;
+       struct at_dma           *atdma = dev_id;
        struct at_dma_chan      *atchan;
        int                     i;
        u32                     status, pending, imr;
@@ -617,23 +826,16 @@ static irqreturn_t at_dma_interrupt(int irq, void *dev_id)
                if (!pending)
                        break;
 
-               dev_vdbg(atdma->dma_common.dev,
+               dev_vdbg(atdma->dma_device.dev,
                        "interrupt: status = 0x%08x, 0x%08x, 0x%08x\n",
                         status, imr, pending);
 
-               for (i = 0; i < atdma->dma_common.chancnt; i++) {
+               for (i = 0; i < atdma->dma_device.chancnt; i++) {
                        atchan = &atdma->chan[i];
-                       if (pending & (AT_DMA_BTC(i) | AT_DMA_ERR(i))) {
-                               if (pending & AT_DMA_ERR(i)) {
-                                       /* Disable channel on AHB error */
-                                       dma_writel(atdma, CHDR,
-                                               AT_DMA_RES(i) | atchan->mask);
-                                       /* Give information to tasklet */
-                                       set_bit(ATC_IS_ERROR, &atchan->status);
-                               }
-                               tasklet_schedule(&atchan->tasklet);
-                               ret = IRQ_HANDLED;
-                       }
+                       if (!(pending & (AT_DMA_BTC(i) | AT_DMA_ERR(i))))
+                               continue;
+                       atdma_handle_chan_done(atchan, pending, i);
+                       ret = IRQ_HANDLED;
                }
 
        } while (pending);
@@ -641,35 +843,7 @@ static irqreturn_t at_dma_interrupt(int irq, void *dev_id)
        return ret;
 }
 
-
 /*--  DMA Engine API  --------------------------------------------------*/
-
-/**
- * atc_tx_submit - set the prepared descriptor(s) to be executed by the engine
- * @tx: descriptor at the head of the transaction chain
- *
- * Queue chain if DMA engine is working already
- *
- * Cookie increment and adding to active_list or queue must be atomic
- */
-static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx)
-{
-       struct at_desc          *desc = txd_to_at_desc(tx);
-       struct at_dma_chan      *atchan = to_at_dma_chan(tx->chan);
-       dma_cookie_t            cookie;
-       unsigned long           flags;
-
-       spin_lock_irqsave(&atchan->lock, flags);
-       cookie = dma_cookie_assign(tx);
-
-       list_add_tail(&desc->desc_node, &atchan->queue);
-       spin_unlock_irqrestore(&atchan->lock, flags);
-
-       dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
-                desc->txd.cookie);
-       return cookie;
-}
-
 /**
  * atc_prep_dma_interleaved - prepare memory to memory interleaved operation
  * @chan: the channel to prepare operation on
@@ -681,9 +855,12 @@ atc_prep_dma_interleaved(struct dma_chan *chan,
                         struct dma_interleaved_template *xt,
                         unsigned long flags)
 {
+       struct at_dma           *atdma = to_at_dma(chan->device);
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct data_chunk       *first;
-       struct at_desc          *desc = NULL;
+       struct atdma_sg         *atdma_sg;
+       struct at_desc          *desc;
+       struct at_lli           *lli;
        size_t                  xfer_count;
        unsigned int            dwidth;
        u32                     ctrla;
@@ -722,8 +899,7 @@ atc_prep_dma_interleaved(struct dma_chan *chan,
                len += chunk->size;
        }
 
-       dwidth = atc_get_xfer_width(xt->src_start,
-                                   xt->dst_start, len);
+       dwidth = atc_get_xfer_width(xt->src_start, xt->dst_start, len);
 
        xfer_count = len >> dwidth;
        if (xfer_count > ATC_BTSIZE_MAX) {
@@ -731,42 +907,43 @@ atc_prep_dma_interleaved(struct dma_chan *chan,
                return NULL;
        }
 
-       ctrla = ATC_SRC_WIDTH(dwidth) |
-               ATC_DST_WIDTH(dwidth);
-
-       ctrlb =   ATC_DEFAULT_CTRLB | ATC_IEN
-               | ATC_SRC_ADDR_MODE_INCR
-               | ATC_DST_ADDR_MODE_INCR
-               | ATC_SRC_PIP
-               | ATC_DST_PIP
-               | ATC_FC_MEM2MEM;
-
-       /* create the transfer */
-       desc = atc_desc_get(atchan);
-       if (!desc) {
-               dev_err(chan2dev(chan),
-                       "%s: couldn't allocate our descriptor\n", __func__);
+       ctrla = FIELD_PREP(ATC_SRC_WIDTH, dwidth) |
+               FIELD_PREP(ATC_DST_WIDTH, dwidth);
+
+       ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN |
+               FIELD_PREP(ATC_SRC_ADDR_MODE, ATC_SRC_ADDR_MODE_INCR) |
+               FIELD_PREP(ATC_DST_ADDR_MODE, ATC_DST_ADDR_MODE_INCR) |
+               ATC_SRC_PIP | ATC_DST_PIP |
+               FIELD_PREP(ATC_FC, ATC_FC_MEM2MEM);
+
+       desc = kzalloc(struct_size(desc, sg, 1), GFP_ATOMIC);
+       if (!desc)
+               return NULL;
+       desc->sglen = 1;
+
+       atdma_sg = desc->sg;
+       atdma_sg->lli = dma_pool_alloc(atdma->lli_pool, GFP_NOWAIT,
+                                      &atdma_sg->lli_phys);
+       if (!atdma_sg->lli) {
+               kfree(desc);
                return NULL;
        }
+       lli = atdma_sg->lli;
 
-       desc->lli.saddr = xt->src_start;
-       desc->lli.daddr = xt->dst_start;
-       desc->lli.ctrla = ctrla | xfer_count;
-       desc->lli.ctrlb = ctrlb;
+       lli->saddr = xt->src_start;
+       lli->daddr = xt->dst_start;
+       lli->ctrla = ctrla | xfer_count;
+       lli->ctrlb = ctrlb;
 
        desc->boundary = first->size >> dwidth;
        desc->dst_hole = (dmaengine_get_dst_icg(xt, first) >> dwidth) + 1;
        desc->src_hole = (dmaengine_get_src_icg(xt, first) >> dwidth) + 1;
 
-       desc->txd.cookie = -EBUSY;
-       desc->total_len = desc->len = len;
-
-       /* set end-of-link to the last link descriptor of list*/
-       set_desc_eol(desc);
-
-       desc->txd.flags = flags; /* client is in control of this ack */
+       atdma_sg->len = len;
+       desc->total_len = len;
 
-       return &desc->txd;
+       set_lli_eol(desc, 0);
+       return vchan_tx_prep(&atchan->vc, &desc->vd, flags);
 }
 
 /**
@@ -781,29 +958,36 @@ static struct dma_async_tx_descriptor *
 atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
                size_t len, unsigned long flags)
 {
+       struct at_dma           *atdma = to_at_dma(chan->device);
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_desc          *desc = NULL;
-       struct at_desc          *first = NULL;
-       struct at_desc          *prev = NULL;
        size_t                  xfer_count;
        size_t                  offset;
+       size_t                  sg_len;
        unsigned int            src_width;
        unsigned int            dst_width;
+       unsigned int            i;
        u32                     ctrla;
        u32                     ctrlb;
 
-       dev_vdbg(chan2dev(chan), "prep_dma_memcpy: d%pad s%pad l0x%zx f0x%lx\n",
-                       &dest, &src, len, flags);
+       dev_dbg(chan2dev(chan), "prep_dma_memcpy: d%pad s%pad l0x%zx f0x%lx\n",
+               &dest, &src, len, flags);
 
        if (unlikely(!len)) {
-               dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
+               dev_err(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
                return NULL;
        }
 
-       ctrlb =   ATC_DEFAULT_CTRLB | ATC_IEN
-               | ATC_SRC_ADDR_MODE_INCR
-               | ATC_DST_ADDR_MODE_INCR
-               | ATC_FC_MEM2MEM;
+       sg_len = DIV_ROUND_UP(len, ATC_BTSIZE_MAX);
+       desc = kzalloc(struct_size(desc, sg, sg_len), GFP_ATOMIC);
+       if (!desc)
+               return NULL;
+       desc->sglen = sg_len;
+
+       ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN |
+               FIELD_PREP(ATC_SRC_ADDR_MODE, ATC_SRC_ADDR_MODE_INCR) |
+               FIELD_PREP(ATC_DST_ADDR_MODE, ATC_DST_ADDR_MODE_INCR) |
+               FIELD_PREP(ATC_FC, ATC_FC_MEM2MEM);
 
        /*
         * We can be a lot more clever here, but this should take care
@@ -811,82 +995,78 @@ atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
         */
        src_width = dst_width = atc_get_xfer_width(src, dest, len);
 
-       ctrla = ATC_SRC_WIDTH(src_width) |
-               ATC_DST_WIDTH(dst_width);
+       ctrla = FIELD_PREP(ATC_SRC_WIDTH, src_width) |
+               FIELD_PREP(ATC_DST_WIDTH, dst_width);
 
-       for (offset = 0; offset < len; offset += xfer_count << src_width) {
-               xfer_count = min_t(size_t, (len - offset) >> src_width,
-                               ATC_BTSIZE_MAX);
+       for (offset = 0, i = 0; offset < len;
+            offset += xfer_count << src_width, i++) {
+               struct atdma_sg *atdma_sg = &desc->sg[i];
+               struct at_lli *lli;
 
-               desc = atc_desc_get(atchan);
-               if (!desc)
+               atdma_sg->lli = dma_pool_alloc(atdma->lli_pool, GFP_NOWAIT,
+                                              &atdma_sg->lli_phys);
+               if (!atdma_sg->lli)
                        goto err_desc_get;
+               lli = atdma_sg->lli;
+
+               xfer_count = min_t(size_t, (len - offset) >> src_width,
+                                  ATC_BTSIZE_MAX);
 
-               desc->lli.saddr = src + offset;
-               desc->lli.daddr = dest + offset;
-               desc->lli.ctrla = ctrla | xfer_count;
-               desc->lli.ctrlb = ctrlb;
+               lli->saddr = src + offset;
+               lli->daddr = dest + offset;
+               lli->ctrla = ctrla | xfer_count;
+               lli->ctrlb = ctrlb;
 
-               desc->txd.cookie = 0;
-               desc->len = xfer_count << src_width;
+               desc->sg[i].len = xfer_count << src_width;
 
-               atc_desc_chain(&first, &prev, desc);
+               atdma_lli_chain(desc, i);
        }
 
-       /* First descriptor of the chain embedds additional information */
-       first->txd.cookie = -EBUSY;
-       first->total_len = len;
+       desc->total_len = len;
 
        /* set end-of-link to the last link descriptor of list*/
-       set_desc_eol(desc);
-
-       first->txd.flags = flags; /* client is in control of this ack */
+       set_lli_eol(desc, i - 1);
 
-       return &first->txd;
+       return vchan_tx_prep(&atchan->vc, &desc->vd, flags);
 
 err_desc_get:
-       atc_desc_put(atchan, first);
+       atdma_desc_free(&desc->vd);
        return NULL;
 }
 
-static struct at_desc *atc_create_memset_desc(struct dma_chan *chan,
-                                             dma_addr_t psrc,
-                                             dma_addr_t pdst,
-                                             size_t len)
+static int atdma_create_memset_lli(struct dma_chan *chan,
+                                  struct atdma_sg *atdma_sg,
+                                  dma_addr_t psrc, dma_addr_t pdst, size_t len)
 {
-       struct at_dma_chan *atchan = to_at_dma_chan(chan);
-       struct at_desc *desc;
+       struct at_dma *atdma = to_at_dma(chan->device);
+       struct at_lli *lli;
        size_t xfer_count;
-
-       u32 ctrla = ATC_SRC_WIDTH(2) | ATC_DST_WIDTH(2);
+       u32 ctrla = FIELD_PREP(ATC_SRC_WIDTH, 2) | FIELD_PREP(ATC_DST_WIDTH, 2);
        u32 ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN |
-               ATC_SRC_ADDR_MODE_FIXED |
-               ATC_DST_ADDR_MODE_INCR |
-               ATC_FC_MEM2MEM;
+                   FIELD_PREP(ATC_SRC_ADDR_MODE, ATC_SRC_ADDR_MODE_FIXED) |
+                   FIELD_PREP(ATC_DST_ADDR_MODE, ATC_DST_ADDR_MODE_INCR) |
+                   FIELD_PREP(ATC_FC, ATC_FC_MEM2MEM);
 
        xfer_count = len >> 2;
        if (xfer_count > ATC_BTSIZE_MAX) {
-               dev_err(chan2dev(chan), "%s: buffer is too big\n",
-                       __func__);
-               return NULL;
+               dev_err(chan2dev(chan), "%s: buffer is too big\n", __func__);
+               return -EINVAL;
        }
 
-       desc = atc_desc_get(atchan);
-       if (!desc) {
-               dev_err(chan2dev(chan), "%s: can't get a descriptor\n",
-                       __func__);
-               return NULL;
-       }
+       atdma_sg->lli = dma_pool_alloc(atdma->lli_pool, GFP_NOWAIT,
+                                      &atdma_sg->lli_phys);
+       if (!atdma_sg->lli)
+               return -ENOMEM;
+       lli = atdma_sg->lli;
 
-       desc->lli.saddr = psrc;
-       desc->lli.daddr = pdst;
-       desc->lli.ctrla = ctrla | xfer_count;
-       desc->lli.ctrlb = ctrlb;
+       lli->saddr = psrc;
+       lli->daddr = pdst;
+       lli->ctrla = ctrla | xfer_count;
+       lli->ctrlb = ctrlb;
 
-       desc->txd.cookie = 0;
-       desc->len = len;
+       atdma_sg->len = len;
 
-       return desc;
+       return 0;
 }
 
 /**
@@ -901,11 +1081,13 @@ static struct dma_async_tx_descriptor *
 atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
                    size_t len, unsigned long flags)
 {
+       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma           *atdma = to_at_dma(chan->device);
        struct at_desc          *desc;
        void __iomem            *vaddr;
        dma_addr_t              paddr;
        char                    fill_pattern;
+       int                     ret;
 
        dev_vdbg(chan2dev(chan), "%s: d%pad v0x%x l0x%zx f0x%lx\n", __func__,
                &dest, value, len, flags);
@@ -936,27 +1118,28 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
                       (fill_pattern << 8) |
                       fill_pattern;
 
-       desc = atc_create_memset_desc(chan, paddr, dest, len);
-       if (!desc) {
-               dev_err(chan2dev(chan), "%s: couldn't get a descriptor\n",
-                       __func__);
+       desc = kzalloc(struct_size(desc, sg, 1), GFP_ATOMIC);
+       if (!desc)
                goto err_free_buffer;
-       }
+       desc->sglen = 1;
+
+       ret = atdma_create_memset_lli(chan, desc->sg, paddr, dest, len);
+       if (ret)
+               goto err_free_desc;
 
        desc->memset_paddr = paddr;
        desc->memset_vaddr = vaddr;
        desc->memset_buffer = true;
 
-       desc->txd.cookie = -EBUSY;
        desc->total_len = len;
 
        /* set end-of-link on the descriptor */
-       set_desc_eol(desc);
-
-       desc->txd.flags = flags;
+       set_lli_eol(desc, 0);
 
-       return &desc->txd;
+       return vchan_tx_prep(&atchan->vc, &desc->vd, flags);
 
+err_free_desc:
+       kfree(desc);
 err_free_buffer:
        dma_pool_free(atdma->memset_pool, vaddr, paddr);
        return NULL;
@@ -970,12 +1153,13 @@ atc_prep_dma_memset_sg(struct dma_chan *chan,
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma           *atdma = to_at_dma(chan->device);
-       struct at_desc          *desc = NULL, *first = NULL, *prev = NULL;
+       struct at_desc          *desc;
        struct scatterlist      *sg;
        void __iomem            *vaddr;
        dma_addr_t              paddr;
        size_t                  total_len = 0;
        int                     i;
+       int                     ret;
 
        dev_vdbg(chan2dev(chan), "%s: v0x%x l0x%zx f0x%lx\n", __func__,
                 value, sg_len, flags);
@@ -994,6 +1178,11 @@ atc_prep_dma_memset_sg(struct dma_chan *chan,
        }
        *(u32*)vaddr = value;
 
+       desc = kzalloc(struct_size(desc, sg, sg_len), GFP_ATOMIC);
+       if (!desc)
+               goto err_free_dma_buf;
+       desc->sglen = sg_len;
+
        for_each_sg(sgl, sg, sg_len, i) {
                dma_addr_t dest = sg_dma_address(sg);
                size_t len = sg_dma_len(sg);
@@ -1004,38 +1193,33 @@ atc_prep_dma_memset_sg(struct dma_chan *chan,
                if (!is_dma_fill_aligned(chan->device, dest, 0, len)) {
                        dev_err(chan2dev(chan), "%s: buffer is not aligned\n",
                                __func__);
-                       goto err_put_desc;
+                       goto err_free_desc;
                }
 
-               desc = atc_create_memset_desc(chan, paddr, dest, len);
-               if (!desc)
-                       goto err_put_desc;
-
-               atc_desc_chain(&first, &prev, desc);
+               ret = atdma_create_memset_lli(chan, &desc->sg[i], paddr, dest,
+                                             len);
+               if (ret)
+                       goto err_free_desc;
 
+               atdma_lli_chain(desc, i);
                total_len += len;
        }
 
-       /*
-        * Only set the buffer pointers on the last descriptor to
-        * avoid free'ing while we have our transfer still going
-        */
        desc->memset_paddr = paddr;
        desc->memset_vaddr = vaddr;
        desc->memset_buffer = true;
 
-       first->txd.cookie = -EBUSY;
-       first->total_len = total_len;
+       desc->total_len = total_len;
 
        /* set end-of-link on the descriptor */
-       set_desc_eol(desc);
-
-       first->txd.flags = flags;
+       set_lli_eol(desc, i - 1);
 
-       return &first->txd;
+       return vchan_tx_prep(&atchan->vc, &desc->vd, flags);
 
-err_put_desc:
-       atc_desc_put(atchan, first);
+err_free_desc:
+       atdma_desc_free(&desc->vd);
+err_free_dma_buf:
+       dma_pool_free(atdma->memset_pool, vaddr, paddr);
        return NULL;
 }
 
@@ -1053,11 +1237,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_transfer_direction direction,
                unsigned long flags, void *context)
 {
+       struct at_dma           *atdma = to_at_dma(chan->device);
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma_slave     *atslave = chan->private;
        struct dma_slave_config *sconfig = &atchan->dma_sconfig;
-       struct at_desc          *first = NULL;
-       struct at_desc          *prev = NULL;
+       struct at_desc          *desc;
        u32                     ctrla;
        u32                     ctrlb;
        dma_addr_t              reg;
@@ -1077,27 +1261,38 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                return NULL;
        }
 
-       ctrla =   ATC_SCSIZE(sconfig->src_maxburst)
-               | ATC_DCSIZE(sconfig->dst_maxburst);
+       desc = kzalloc(struct_size(desc, sg, sg_len), GFP_ATOMIC);
+       if (!desc)
+               return NULL;
+       desc->sglen = sg_len;
+
+       ctrla = FIELD_PREP(ATC_SCSIZE, sconfig->src_maxburst) |
+               FIELD_PREP(ATC_DCSIZE, sconfig->dst_maxburst);
        ctrlb = ATC_IEN;
 
        switch (direction) {
        case DMA_MEM_TO_DEV:
                reg_width = convert_buswidth(sconfig->dst_addr_width);
-               ctrla |=  ATC_DST_WIDTH(reg_width);
-               ctrlb |=  ATC_DST_ADDR_MODE_FIXED
-                       | ATC_SRC_ADDR_MODE_INCR
-                       | ATC_FC_MEM2PER
-                       | ATC_SIF(atchan->mem_if) | ATC_DIF(atchan->per_if);
+               ctrla |= FIELD_PREP(ATC_DST_WIDTH, reg_width);
+               ctrlb |= FIELD_PREP(ATC_DST_ADDR_MODE,
+                                   ATC_DST_ADDR_MODE_FIXED) |
+                        FIELD_PREP(ATC_SRC_ADDR_MODE, ATC_SRC_ADDR_MODE_INCR) |
+                        FIELD_PREP(ATC_FC, ATC_FC_MEM2PER) |
+                        FIELD_PREP(ATC_SIF, atchan->mem_if) |
+                        FIELD_PREP(ATC_DIF, atchan->per_if);
                reg = sconfig->dst_addr;
                for_each_sg(sgl, sg, sg_len, i) {
-                       struct at_desc  *desc;
+                       struct atdma_sg *atdma_sg = &desc->sg[i];
+                       struct at_lli *lli;
                        u32             len;
                        u32             mem;
 
-                       desc = atc_desc_get(atchan);
-                       if (!desc)
+                       atdma_sg->lli = dma_pool_alloc(atdma->lli_pool,
+                                                      GFP_NOWAIT,
+                                                      &atdma_sg->lli_phys);
+                       if (!atdma_sg->lli)
                                goto err_desc_get;
+                       lli = atdma_sg->lli;
 
                        mem = sg_dma_address(sg);
                        len = sg_dma_len(sg);
@@ -1110,35 +1305,43 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        if (unlikely(mem & 3 || len & 3))
                                mem_width = 0;
 
-                       desc->lli.saddr = mem;
-                       desc->lli.daddr = reg;
-                       desc->lli.ctrla = ctrla
-                                       | ATC_SRC_WIDTH(mem_width)
-                                       | len >> mem_width;
-                       desc->lli.ctrlb = ctrlb;
-                       desc->len = len;
+                       lli->saddr = mem;
+                       lli->daddr = reg;
+                       lli->ctrla = ctrla |
+                                    FIELD_PREP(ATC_SRC_WIDTH, mem_width) |
+                                    len >> mem_width;
+                       lli->ctrlb = ctrlb;
 
-                       atc_desc_chain(&first, &prev, desc);
+                       atdma_sg->len = len;
                        total_len += len;
+
+                       desc->sg[i].len = len;
+                       atdma_lli_chain(desc, i);
                }
                break;
        case DMA_DEV_TO_MEM:
                reg_width = convert_buswidth(sconfig->src_addr_width);
-               ctrla |=  ATC_SRC_WIDTH(reg_width);
-               ctrlb |=  ATC_DST_ADDR_MODE_INCR
-                       | ATC_SRC_ADDR_MODE_FIXED
-                       | ATC_FC_PER2MEM
-                       | ATC_SIF(atchan->per_if) | ATC_DIF(atchan->mem_if);
+               ctrla |= FIELD_PREP(ATC_SRC_WIDTH, reg_width);
+               ctrlb |= FIELD_PREP(ATC_DST_ADDR_MODE, ATC_DST_ADDR_MODE_INCR) |
+                        FIELD_PREP(ATC_SRC_ADDR_MODE,
+                                   ATC_SRC_ADDR_MODE_FIXED) |
+                        FIELD_PREP(ATC_FC, ATC_FC_PER2MEM) |
+                        FIELD_PREP(ATC_SIF, atchan->per_if) |
+                        FIELD_PREP(ATC_DIF, atchan->mem_if);
 
                reg = sconfig->src_addr;
                for_each_sg(sgl, sg, sg_len, i) {
-                       struct at_desc  *desc;
+                       struct atdma_sg *atdma_sg = &desc->sg[i];
+                       struct at_lli *lli;
                        u32             len;
                        u32             mem;
 
-                       desc = atc_desc_get(atchan);
-                       if (!desc)
+                       atdma_sg->lli = dma_pool_alloc(atdma->lli_pool,
+                                                      GFP_NOWAIT,
+                                                      &atdma_sg->lli_phys);
+                       if (!atdma_sg->lli)
                                goto err_desc_get;
+                       lli = atdma_sg->lli;
 
                        mem = sg_dma_address(sg);
                        len = sg_dma_len(sg);
@@ -1151,16 +1354,17 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        if (unlikely(mem & 3 || len & 3))
                                mem_width = 0;
 
-                       desc->lli.saddr = reg;
-                       desc->lli.daddr = mem;
-                       desc->lli.ctrla = ctrla
-                                       | ATC_DST_WIDTH(mem_width)
-                                       | len >> reg_width;
-                       desc->lli.ctrlb = ctrlb;
-                       desc->len = len;
+                       lli->saddr = reg;
+                       lli->daddr = mem;
+                       lli->ctrla = ctrla |
+                                    FIELD_PREP(ATC_DST_WIDTH, mem_width) |
+                                    len >> reg_width;
+                       lli->ctrlb = ctrlb;
 
-                       atc_desc_chain(&first, &prev, desc);
+                       desc->sg[i].len = len;
                        total_len += len;
+
+                       atdma_lli_chain(desc, i);
                }
                break;
        default:
@@ -1168,21 +1372,16 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
        }
 
        /* set end-of-link to the last link descriptor of list*/
-       set_desc_eol(prev);
+       set_lli_eol(desc, i - 1);
 
-       /* First descriptor of the chain embedds additional information */
-       first->txd.cookie = -EBUSY;
-       first->total_len = total_len;
+       desc->total_len = total_len;
 
-       /* first link descriptor of list is responsible of flags */
-       first->txd.flags = flags; /* client is in control of this ack */
-
-       return &first->txd;
+       return vchan_tx_prep(&atchan->vc, &desc->vd, flags);
 
 err_desc_get:
        dev_err(chan2dev(chan), "not enough descriptors available\n");
 err:
-       atc_desc_put(atchan, first);
+       atdma_desc_free(&desc->vd);
        return NULL;
 }
 
@@ -1212,50 +1411,59 @@ err_out:
  */
 static int
 atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc,
-               unsigned int period_index, dma_addr_t buf_addr,
+               unsigned int i, dma_addr_t buf_addr,
                unsigned int reg_width, size_t period_len,
                enum dma_transfer_direction direction)
 {
+       struct at_dma           *atdma = to_at_dma(chan->device);
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct dma_slave_config *sconfig = &atchan->dma_sconfig;
-       u32                     ctrla;
+       struct atdma_sg         *atdma_sg = &desc->sg[i];
+       struct at_lli           *lli;
 
-       /* prepare common CRTLA value */
-       ctrla =   ATC_SCSIZE(sconfig->src_maxburst)
-               | ATC_DCSIZE(sconfig->dst_maxburst)
-               | ATC_DST_WIDTH(reg_width)
-               | ATC_SRC_WIDTH(reg_width)
-               | period_len >> reg_width;
+       atdma_sg->lli = dma_pool_alloc(atdma->lli_pool, GFP_ATOMIC,
+                                      &atdma_sg->lli_phys);
+       if (!atdma_sg->lli)
+               return -ENOMEM;
+       lli = atdma_sg->lli;
 
        switch (direction) {
        case DMA_MEM_TO_DEV:
-               desc->lli.saddr = buf_addr + (period_len * period_index);
-               desc->lli.daddr = sconfig->dst_addr;
-               desc->lli.ctrla = ctrla;
-               desc->lli.ctrlb = ATC_DST_ADDR_MODE_FIXED
-                               | ATC_SRC_ADDR_MODE_INCR
-                               | ATC_FC_MEM2PER
-                               | ATC_SIF(atchan->mem_if)
-                               | ATC_DIF(atchan->per_if);
-               desc->len = period_len;
+               lli->saddr = buf_addr + (period_len * i);
+               lli->daddr = sconfig->dst_addr;
+               lli->ctrlb = FIELD_PREP(ATC_DST_ADDR_MODE,
+                                       ATC_DST_ADDR_MODE_FIXED) |
+                            FIELD_PREP(ATC_SRC_ADDR_MODE,
+                                       ATC_SRC_ADDR_MODE_INCR) |
+                            FIELD_PREP(ATC_FC, ATC_FC_MEM2PER) |
+                            FIELD_PREP(ATC_SIF, atchan->mem_if) |
+                            FIELD_PREP(ATC_DIF, atchan->per_if);
+
                break;
 
        case DMA_DEV_TO_MEM:
-               desc->lli.saddr = sconfig->src_addr;
-               desc->lli.daddr = buf_addr + (period_len * period_index);
-               desc->lli.ctrla = ctrla;
-               desc->lli.ctrlb = ATC_DST_ADDR_MODE_INCR
-                               | ATC_SRC_ADDR_MODE_FIXED
-                               | ATC_FC_PER2MEM
-                               | ATC_SIF(atchan->per_if)
-                               | ATC_DIF(atchan->mem_if);
-               desc->len = period_len;
+               lli->saddr = sconfig->src_addr;
+               lli->daddr = buf_addr + (period_len * i);
+               lli->ctrlb = FIELD_PREP(ATC_DST_ADDR_MODE,
+                                       ATC_DST_ADDR_MODE_INCR) |
+                            FIELD_PREP(ATC_SRC_ADDR_MODE,
+                                       ATC_SRC_ADDR_MODE_FIXED) |
+                            FIELD_PREP(ATC_FC, ATC_FC_PER2MEM) |
+                            FIELD_PREP(ATC_SIF, atchan->per_if) |
+                            FIELD_PREP(ATC_DIF, atchan->mem_if);
                break;
 
        default:
                return -EINVAL;
        }
 
+       lli->ctrla = FIELD_PREP(ATC_SCSIZE, sconfig->src_maxburst) |
+                    FIELD_PREP(ATC_DCSIZE, sconfig->dst_maxburst) |
+                    FIELD_PREP(ATC_DST_WIDTH, reg_width) |
+                    FIELD_PREP(ATC_SRC_WIDTH, reg_width) |
+                    period_len >> reg_width;
+       desc->sg[i].len = period_len;
+
        return 0;
 }
 
@@ -1276,8 +1484,7 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma_slave     *atslave = chan->private;
        struct dma_slave_config *sconfig = &atchan->dma_sconfig;
-       struct at_desc          *first = NULL;
-       struct at_desc          *prev = NULL;
+       struct at_desc          *desc;
        unsigned long           was_cyclic;
        unsigned int            reg_width;
        unsigned int            periods = buf_len / period_len;
@@ -1311,33 +1518,26 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
        if (atc_dma_cyclic_check_values(reg_width, buf_addr, period_len))
                goto err_out;
 
+       desc = kzalloc(struct_size(desc, sg, periods), GFP_ATOMIC);
+       if (!desc)
+               goto err_out;
+       desc->sglen = periods;
+
        /* build cyclic linked list */
        for (i = 0; i < periods; i++) {
-               struct at_desc  *desc;
-
-               desc = atc_desc_get(atchan);
-               if (!desc)
-                       goto err_desc_get;
-
                if (atc_dma_cyclic_fill_desc(chan, desc, i, buf_addr,
                                             reg_width, period_len, direction))
-                       goto err_desc_get;
-
-               atc_desc_chain(&first, &prev, desc);
+                       goto err_fill_desc;
+               atdma_lli_chain(desc, i);
        }
-
+       desc->total_len = buf_len;
        /* lets make a cyclic list */
-       prev->lli.dscr = first->txd.phys;
+       desc->sg[i - 1].lli->dscr = desc->sg[0].lli_phys;
 
-       /* First descriptor of the chain embedds additional information */
-       first->txd.cookie = -EBUSY;
-       first->total_len = buf_len;
+       return vchan_tx_prep(&atchan->vc, &desc->vd, flags);
 
-       return &first->txd;
-
-err_desc_get:
-       dev_err(chan2dev(chan), "not enough descriptors available\n");
-       atc_desc_put(atchan, first);
+err_fill_desc:
+       atdma_desc_free(&desc->vd);
 err_out:
        clear_bit(ATC_IS_CYCLIC, &atchan->status);
        return NULL;
@@ -1366,17 +1566,17 @@ static int atc_pause(struct dma_chan *chan)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma           *atdma = to_at_dma(chan->device);
-       int                     chan_id = atchan->chan_common.chan_id;
+       int                     chan_id = atchan->vc.chan.chan_id;
        unsigned long           flags;
 
        dev_vdbg(chan2dev(chan), "%s\n", __func__);
 
-       spin_lock_irqsave(&atchan->lock, flags);
+       spin_lock_irqsave(&atchan->vc.lock, flags);
 
        dma_writel(atdma, CHER, AT_DMA_SUSP(chan_id));
        set_bit(ATC_IS_PAUSED, &atchan->status);
 
-       spin_unlock_irqrestore(&atchan->lock, flags);
+       spin_unlock_irqrestore(&atchan->vc.lock, flags);
 
        return 0;
 }
@@ -1385,7 +1585,7 @@ static int atc_resume(struct dma_chan *chan)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma           *atdma = to_at_dma(chan->device);
-       int                     chan_id = atchan->chan_common.chan_id;
+       int                     chan_id = atchan->vc.chan.chan_id;
        unsigned long           flags;
 
        dev_vdbg(chan2dev(chan), "%s\n", __func__);
@@ -1393,12 +1593,12 @@ static int atc_resume(struct dma_chan *chan)
        if (!atc_chan_is_paused(atchan))
                return 0;
 
-       spin_lock_irqsave(&atchan->lock, flags);
+       spin_lock_irqsave(&atchan->vc.lock, flags);
 
        dma_writel(atdma, CHDR, AT_DMA_RES(chan_id));
        clear_bit(ATC_IS_PAUSED, &atchan->status);
 
-       spin_unlock_irqrestore(&atchan->lock, flags);
+       spin_unlock_irqrestore(&atchan->vc.lock, flags);
 
        return 0;
 }
@@ -1407,9 +1607,11 @@ static int atc_terminate_all(struct dma_chan *chan)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma           *atdma = to_at_dma(chan->device);
-       int                     chan_id = atchan->chan_common.chan_id;
+       int                     chan_id = atchan->vc.chan.chan_id;
        unsigned long           flags;
 
+       LIST_HEAD(list);
+
        dev_vdbg(chan2dev(chan), "%s\n", __func__);
 
        /*
@@ -1418,7 +1620,7 @@ static int atc_terminate_all(struct dma_chan *chan)
         * channel. We still have to poll the channel enable bit due
         * to AHB/HSB limitations.
         */
-       spin_lock_irqsave(&atchan->lock, flags);
+       spin_lock_irqsave(&atchan->vc.lock, flags);
 
        /* disabling channel: must also remove suspend state */
        dma_writel(atdma, CHDR, AT_DMA_RES(chan_id) | atchan->mask);
@@ -1427,15 +1629,20 @@ static int atc_terminate_all(struct dma_chan *chan)
        while (dma_readl(atdma, CHSR) & atchan->mask)
                cpu_relax();
 
-       /* active_list entries will end up before queued entries */
-       list_splice_tail_init(&atchan->queue, &atchan->free_list);
-       list_splice_tail_init(&atchan->active_list, &atchan->free_list);
+       if (atchan->desc) {
+               vchan_terminate_vdesc(&atchan->desc->vd);
+               atchan->desc = NULL;
+       }
+
+       vchan_get_all_descriptors(&atchan->vc, &list);
 
        clear_bit(ATC_IS_PAUSED, &atchan->status);
        /* if channel dedicated to cyclic operations, free it */
        clear_bit(ATC_IS_CYCLIC, &atchan->status);
 
-       spin_unlock_irqrestore(&atchan->lock, flags);
+       spin_unlock_irqrestore(&atchan->vc.lock, flags);
+
+       vchan_dma_desc_free_list(&atchan->vc, &list);
 
        return 0;
 }
@@ -1457,60 +1664,43 @@ atc_tx_status(struct dma_chan *chan,
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        unsigned long           flags;
-       enum dma_status         ret;
-       int bytes = 0;
-
-       ret = dma_cookie_status(chan, cookie, txstate);
-       if (ret == DMA_COMPLETE)
-               return ret;
-       /*
-        * There's no point calculating the residue if there's
-        * no txstate to store the value.
-        */
-       if (!txstate)
-               return DMA_ERROR;
+       enum dma_status         dma_status;
+       u32 residue;
+       int ret;
 
-       spin_lock_irqsave(&atchan->lock, flags);
+       dma_status = dma_cookie_status(chan, cookie, txstate);
+       if (dma_status == DMA_COMPLETE || !txstate)
+               return dma_status;
 
+       spin_lock_irqsave(&atchan->vc.lock, flags);
        /*  Get number of bytes left in the active transactions */
-       bytes = atc_get_bytes_left(chan, cookie);
-
-       spin_unlock_irqrestore(&atchan->lock, flags);
+       ret = atc_get_residue(chan, cookie, &residue);
+       spin_unlock_irqrestore(&atchan->vc.lock, flags);
 
-       if (unlikely(bytes < 0)) {
+       if (unlikely(ret < 0)) {
                dev_vdbg(chan2dev(chan), "get residual bytes error\n");
                return DMA_ERROR;
        } else {
-               dma_set_residue(txstate, bytes);
+               dma_set_residue(txstate, residue);
        }
 
-       dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d residue = %d\n",
-                ret, cookie, bytes);
+       dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d residue = %u\n",
+                dma_status, cookie, residue);
 
-       return ret;
+       return dma_status;
 }
 
-/**
- * atc_issue_pending - takes the first transaction descriptor in the pending
- * queue and starts the transfer.
- * @chan: target DMA channel
- */
 static void atc_issue_pending(struct dma_chan *chan)
 {
        struct at_dma_chan *atchan = to_at_dma_chan(chan);
-       struct at_desc *desc;
        unsigned long flags;
 
-       dev_vdbg(chan2dev(chan), "issue_pending\n");
-
-       spin_lock_irqsave(&atchan->lock, flags);
-       if (atc_chan_is_enabled(atchan) || list_empty(&atchan->queue))
-               return spin_unlock_irqrestore(&atchan->lock, flags);
-
-       desc = atc_first_queued(atchan);
-       list_move_tail(&desc->desc_node, &atchan->active_list);
-       atc_dostart(atchan, desc);
-       spin_unlock_irqrestore(&atchan->lock, flags);
+       spin_lock_irqsave(&atchan->vc.lock, flags);
+       if (vchan_issue_pending(&atchan->vc) && !atchan->desc) {
+               if (!(atc_chan_is_enabled(atchan)))
+                       atc_dostart(atchan);
+       }
+       spin_unlock_irqrestore(&atchan->vc.lock, flags);
 }
 
 /**
@@ -1523,9 +1713,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
        struct at_dma           *atdma = to_at_dma(chan->device);
-       struct at_desc          *desc;
        struct at_dma_slave     *atslave;
-       int                     i;
        u32                     cfg;
 
        dev_vdbg(chan2dev(chan), "alloc_chan_resources\n");
@@ -1536,11 +1724,6 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
                return -EIO;
        }
 
-       if (!list_empty(&atchan->free_list)) {
-               dev_dbg(chan2dev(chan), "can't allocate channel resources (channel not freed from a previous use)\n");
-               return -EIO;
-       }
-
        cfg = ATC_DEFAULT_CFG;
 
        atslave = chan->private;
@@ -1549,33 +1732,17 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
                 * We need controller-specific data to set up slave
                 * transfers.
                 */
-               BUG_ON(!atslave->dma_dev || atslave->dma_dev != atdma->dma_common.dev);
+               BUG_ON(!atslave->dma_dev || atslave->dma_dev != atdma->dma_device.dev);
 
                /* if cfg configuration specified take it instead of default */
                if (atslave->cfg)
                        cfg = atslave->cfg;
        }
 
-       /* Allocate initial pool of descriptors */
-       for (i = 0; i < init_nr_desc_per_channel; i++) {
-               desc = atc_alloc_descriptor(chan, GFP_KERNEL);
-               if (!desc) {
-                       dev_err(atdma->dma_common.dev,
-                               "Only %d initial descriptors\n", i);
-                       break;
-               }
-               list_add_tail(&desc->desc_node, &atchan->free_list);
-       }
-
-       dma_cookie_init(chan);
-
        /* channel parameters */
        channel_writel(atchan, CFG, cfg);
 
-       dev_dbg(chan2dev(chan),
-               "alloc_chan_resources: allocated %d descriptors\n", i);
-
-       return i;
+       return 0;
 }
 
 /**
@@ -1585,22 +1752,10 @@ static int atc_alloc_chan_resources(struct dma_chan *chan)
 static void atc_free_chan_resources(struct dma_chan *chan)
 {
        struct at_dma_chan      *atchan = to_at_dma_chan(chan);
-       struct at_dma           *atdma = to_at_dma(chan->device);
-       struct at_desc          *desc, *_desc;
-       LIST_HEAD(list);
 
-       /* ASSERT:  channel is idle */
-       BUG_ON(!list_empty(&atchan->active_list));
-       BUG_ON(!list_empty(&atchan->queue));
        BUG_ON(atc_chan_is_enabled(atchan));
 
-       list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) {
-               dev_vdbg(chan2dev(chan), "  freeing descriptor %p\n", desc);
-               list_del(&desc->desc_node);
-               /* free link descriptor */
-               dma_pool_free(atdma->dma_desc_pool, desc, desc->txd.phys);
-       }
-       list_splice_init(&atchan->free_list, &list);
+       vchan_free_chan_resources(to_virt_chan(chan));
        atchan->status = 0;
 
        /*
@@ -1651,14 +1806,13 @@ static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec,
                return NULL;
        }
 
-       atslave->cfg = ATC_DST_H2SEL_HW | ATC_SRC_H2SEL_HW;
+       atslave->cfg = ATC_DST_H2SEL | ATC_SRC_H2SEL;
        /*
         * We can fill both SRC_PER and DST_PER, one of these fields will be
         * ignored depending on DMA transfer direction.
         */
        per_id = dma_spec->args[1] & AT91_DMA_CFG_PER_ID_MASK;
-       atslave->cfg |= ATC_DST_PER_MSB(per_id) | ATC_DST_PER(per_id)
-                    | ATC_SRC_PER_MSB(per_id) | ATC_SRC_PER(per_id);
+       atslave->cfg |= ATC_DST_PER_ID(per_id) |  ATC_SRC_PER_ID(per_id);
        /*
         * We have to translate the value we get from the device tree since
         * the half FIFO configuration value had to be 0 to keep backward
@@ -1666,14 +1820,16 @@ static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec,
         */
        switch (dma_spec->args[1] & AT91_DMA_CFG_FIFOCFG_MASK) {
        case AT91_DMA_CFG_FIFOCFG_ALAP:
-               atslave->cfg |= ATC_FIFOCFG_LARGESTBURST;
+               atslave->cfg |= FIELD_PREP(ATC_FIFOCFG,
+                                          ATC_FIFOCFG_LARGESTBURST);
                break;
        case AT91_DMA_CFG_FIFOCFG_ASAP:
-               atslave->cfg |= ATC_FIFOCFG_ENOUGHSPACE;
+               atslave->cfg |= FIELD_PREP(ATC_FIFOCFG,
+                                          ATC_FIFOCFG_ENOUGHSPACE);
                break;
        case AT91_DMA_CFG_FIFOCFG_HALF:
        default:
-               atslave->cfg |= ATC_FIFOCFG_HALFFIFO;
+               atslave->cfg |= FIELD_PREP(ATC_FIFOCFG, ATC_FIFOCFG_HALFFIFO);
        }
        atslave->dma_dev = &dmac_pdev->dev;
 
@@ -1768,9 +1924,7 @@ static void at_dma_off(struct at_dma *atdma)
 
 static int __init at_dma_probe(struct platform_device *pdev)
 {
-       struct resource         *io;
        struct at_dma           *atdma;
-       size_t                  size;
        int                     irq;
        int                     err;
        int                     i;
@@ -1790,44 +1944,31 @@ static int __init at_dma_probe(struct platform_device *pdev)
        if (!plat_dat)
                return -ENODEV;
 
-       io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!io)
-               return -EINVAL;
+       atdma = devm_kzalloc(&pdev->dev,
+                            struct_size(atdma, chan, plat_dat->nr_channels),
+                            GFP_KERNEL);
+       if (!atdma)
+               return -ENOMEM;
+
+       atdma->regs = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(atdma->regs))
+               return PTR_ERR(atdma->regs);
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
                return irq;
 
-       size = sizeof(struct at_dma);
-       size += plat_dat->nr_channels * sizeof(struct at_dma_chan);
-       atdma = kzalloc(size, GFP_KERNEL);
-       if (!atdma)
-               return -ENOMEM;
-
        /* discover transaction capabilities */
-       atdma->dma_common.cap_mask = plat_dat->cap_mask;
+       atdma->dma_device.cap_mask = plat_dat->cap_mask;
        atdma->all_chan_mask = (1 << plat_dat->nr_channels) - 1;
 
-       size = resource_size(io);
-       if (!request_mem_region(io->start, size, pdev->dev.driver->name)) {
-               err = -EBUSY;
-               goto err_kfree;
-       }
-
-       atdma->regs = ioremap(io->start, size);
-       if (!atdma->regs) {
-               err = -ENOMEM;
-               goto err_release_r;
-       }
+       atdma->clk = devm_clk_get(&pdev->dev, "dma_clk");
+       if (IS_ERR(atdma->clk))
+               return PTR_ERR(atdma->clk);
 
-       atdma->clk = clk_get(&pdev->dev, "dma_clk");
-       if (IS_ERR(atdma->clk)) {
-               err = PTR_ERR(atdma->clk);
-               goto err_clk;
-       }
        err = clk_prepare_enable(atdma->clk);
        if (err)
-               goto err_clk_prepare;
+               return err;
 
        /* force dma off, just in case */
        at_dma_off(atdma);
@@ -1839,11 +1980,11 @@ static int __init at_dma_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, atdma);
 
        /* create a pool of consistent memory blocks for hardware descriptors */
-       atdma->dma_desc_pool = dma_pool_create("at_hdmac_desc_pool",
-                       &pdev->dev, sizeof(struct at_desc),
-                       4 /* word alignment */, 0);
-       if (!atdma->dma_desc_pool) {
-               dev_err(&pdev->dev, "No memory for descriptors dma pool\n");
+       atdma->lli_pool = dma_pool_create("at_hdmac_lli_pool",
+                                         &pdev->dev, sizeof(struct at_lli),
+                                         4 /* word alignment */, 0);
+       if (!atdma->lli_pool) {
+               dev_err(&pdev->dev, "Unable to allocate DMA LLI descriptor pool\n");
                err = -ENOMEM;
                goto err_desc_pool_create;
        }
@@ -1862,73 +2003,66 @@ static int __init at_dma_probe(struct platform_device *pdev)
                cpu_relax();
 
        /* initialize channels related values */
-       INIT_LIST_HEAD(&atdma->dma_common.channels);
+       INIT_LIST_HEAD(&atdma->dma_device.channels);
        for (i = 0; i < plat_dat->nr_channels; i++) {
                struct at_dma_chan      *atchan = &atdma->chan[i];
 
                atchan->mem_if = AT_DMA_MEM_IF;
                atchan->per_if = AT_DMA_PER_IF;
-               atchan->chan_common.device = &atdma->dma_common;
-               dma_cookie_init(&atchan->chan_common);
-               list_add_tail(&atchan->chan_common.device_node,
-                               &atdma->dma_common.channels);
 
                atchan->ch_regs = atdma->regs + ch_regs(i);
-               spin_lock_init(&atchan->lock);
                atchan->mask = 1 << i;
 
-               INIT_LIST_HEAD(&atchan->active_list);
-               INIT_LIST_HEAD(&atchan->queue);
-               INIT_LIST_HEAD(&atchan->free_list);
-
-               tasklet_setup(&atchan->tasklet, atc_tasklet);
+               atchan->atdma = atdma;
+               atchan->vc.desc_free = atdma_desc_free;
+               vchan_init(&atchan->vc, &atdma->dma_device);
                atc_enable_chan_irq(atdma, i);
        }
 
        /* set base routines */
-       atdma->dma_common.device_alloc_chan_resources = atc_alloc_chan_resources;
-       atdma->dma_common.device_free_chan_resources = atc_free_chan_resources;
-       atdma->dma_common.device_tx_status = atc_tx_status;
-       atdma->dma_common.device_issue_pending = atc_issue_pending;
-       atdma->dma_common.dev = &pdev->dev;
+       atdma->dma_device.device_alloc_chan_resources = atc_alloc_chan_resources;
+       atdma->dma_device.device_free_chan_resources = atc_free_chan_resources;
+       atdma->dma_device.device_tx_status = atc_tx_status;
+       atdma->dma_device.device_issue_pending = atc_issue_pending;
+       atdma->dma_device.dev = &pdev->dev;
 
        /* set prep routines based on capability */
-       if (dma_has_cap(DMA_INTERLEAVE, atdma->dma_common.cap_mask))
-               atdma->dma_common.device_prep_interleaved_dma = atc_prep_dma_interleaved;
+       if (dma_has_cap(DMA_INTERLEAVE, atdma->dma_device.cap_mask))
+               atdma->dma_device.device_prep_interleaved_dma = atc_prep_dma_interleaved;
 
-       if (dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask))
-               atdma->dma_common.device_prep_dma_memcpy = atc_prep_dma_memcpy;
+       if (dma_has_cap(DMA_MEMCPY, atdma->dma_device.cap_mask))
+               atdma->dma_device.device_prep_dma_memcpy = atc_prep_dma_memcpy;
 
-       if (dma_has_cap(DMA_MEMSET, atdma->dma_common.cap_mask)) {
-               atdma->dma_common.device_prep_dma_memset = atc_prep_dma_memset;
-               atdma->dma_common.device_prep_dma_memset_sg = atc_prep_dma_memset_sg;
-               atdma->dma_common.fill_align = DMAENGINE_ALIGN_4_BYTES;
+       if (dma_has_cap(DMA_MEMSET, atdma->dma_device.cap_mask)) {
+               atdma->dma_device.device_prep_dma_memset = atc_prep_dma_memset;
+               atdma->dma_device.device_prep_dma_memset_sg = atc_prep_dma_memset_sg;
+               atdma->dma_device.fill_align = DMAENGINE_ALIGN_4_BYTES;
        }
 
-       if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)) {
-               atdma->dma_common.device_prep_slave_sg = atc_prep_slave_sg;
+       if (dma_has_cap(DMA_SLAVE, atdma->dma_device.cap_mask)) {
+               atdma->dma_device.device_prep_slave_sg = atc_prep_slave_sg;
                /* controller can do slave DMA: can trigger cyclic transfers */
-               dma_cap_set(DMA_CYCLIC, atdma->dma_common.cap_mask);
-               atdma->dma_common.device_prep_dma_cyclic = atc_prep_dma_cyclic;
-               atdma->dma_common.device_config = atc_config;
-               atdma->dma_common.device_pause = atc_pause;
-               atdma->dma_common.device_resume = atc_resume;
-               atdma->dma_common.device_terminate_all = atc_terminate_all;
-               atdma->dma_common.src_addr_widths = ATC_DMA_BUSWIDTHS;
-               atdma->dma_common.dst_addr_widths = ATC_DMA_BUSWIDTHS;
-               atdma->dma_common.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
-               atdma->dma_common.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+               dma_cap_set(DMA_CYCLIC, atdma->dma_device.cap_mask);
+               atdma->dma_device.device_prep_dma_cyclic = atc_prep_dma_cyclic;
+               atdma->dma_device.device_config = atc_config;
+               atdma->dma_device.device_pause = atc_pause;
+               atdma->dma_device.device_resume = atc_resume;
+               atdma->dma_device.device_terminate_all = atc_terminate_all;
+               atdma->dma_device.src_addr_widths = ATC_DMA_BUSWIDTHS;
+               atdma->dma_device.dst_addr_widths = ATC_DMA_BUSWIDTHS;
+               atdma->dma_device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+               atdma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
        }
 
        dma_writel(atdma, EN, AT_DMA_ENABLE);
 
        dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s%s), %d channels\n",
-         dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
-         dma_has_cap(DMA_MEMSET, atdma->dma_common.cap_mask) ? "set " : "",
-         dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)  ? "slave " : "",
+         dma_has_cap(DMA_MEMCPY, atdma->dma_device.cap_mask) ? "cpy " : "",
+         dma_has_cap(DMA_MEMSET, atdma->dma_device.cap_mask) ? "set " : "",
+         dma_has_cap(DMA_SLAVE, atdma->dma_device.cap_mask)  ? "slave " : "",
          plat_dat->nr_channels);
 
-       err = dma_async_device_register(&atdma->dma_common);
+       err = dma_async_device_register(&atdma->dma_device);
        if (err) {
                dev_err(&pdev->dev, "Unable to register: %d.\n", err);
                goto err_dma_async_device_register;
@@ -1951,24 +2085,15 @@ static int __init at_dma_probe(struct platform_device *pdev)
        return 0;
 
 err_of_dma_controller_register:
-       dma_async_device_unregister(&atdma->dma_common);
+       dma_async_device_unregister(&atdma->dma_device);
 err_dma_async_device_register:
        dma_pool_destroy(atdma->memset_pool);
 err_memset_pool_create:
-       dma_pool_destroy(atdma->dma_desc_pool);
+       dma_pool_destroy(atdma->lli_pool);
 err_desc_pool_create:
        free_irq(platform_get_irq(pdev, 0), atdma);
 err_irq:
        clk_disable_unprepare(atdma->clk);
-err_clk_prepare:
-       clk_put(atdma->clk);
-err_clk:
-       iounmap(atdma->regs);
-       atdma->regs = NULL;
-err_release_r:
-       release_mem_region(io->start, size);
-err_kfree:
-       kfree(atdma);
        return err;
 }
 
@@ -1976,38 +2101,24 @@ static int at_dma_remove(struct platform_device *pdev)
 {
        struct at_dma           *atdma = platform_get_drvdata(pdev);
        struct dma_chan         *chan, *_chan;
-       struct resource         *io;
 
        at_dma_off(atdma);
        if (pdev->dev.of_node)
                of_dma_controller_free(pdev->dev.of_node);
-       dma_async_device_unregister(&atdma->dma_common);
+       dma_async_device_unregister(&atdma->dma_device);
 
        dma_pool_destroy(atdma->memset_pool);
-       dma_pool_destroy(atdma->dma_desc_pool);
+       dma_pool_destroy(atdma->lli_pool);
        free_irq(platform_get_irq(pdev, 0), atdma);
 
-       list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+       list_for_each_entry_safe(chan, _chan, &atdma->dma_device.channels,
                        device_node) {
-               struct at_dma_chan      *atchan = to_at_dma_chan(chan);
-
                /* Disable interrupts */
                atc_disable_chan_irq(atdma, chan->chan_id);
-
-               tasklet_kill(&atchan->tasklet);
                list_del(&chan->device_node);
        }
 
        clk_disable_unprepare(atdma->clk);
-       clk_put(atdma->clk);
-
-       iounmap(atdma->regs);
-       atdma->regs = NULL;
-
-       io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(io->start, resource_size(io));
-
-       kfree(atdma);
 
        return 0;
 }
@@ -2025,7 +2136,7 @@ static int at_dma_prepare(struct device *dev)
        struct at_dma *atdma = dev_get_drvdata(dev);
        struct dma_chan *chan, *_chan;
 
-       list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+       list_for_each_entry_safe(chan, _chan, &atdma->dma_device.channels,
                        device_node) {
                struct at_dma_chan *atchan = to_at_dma_chan(chan);
                /* wait for transaction completion (except in cyclic case) */
@@ -2037,7 +2148,7 @@ static int at_dma_prepare(struct device *dev)
 
 static void atc_suspend_cyclic(struct at_dma_chan *atchan)
 {
-       struct dma_chan *chan = &atchan->chan_common;
+       struct dma_chan *chan = &atchan->vc.chan;
 
        /* Channel should be paused by user
         * do it anyway even if it is not done already */
@@ -2060,7 +2171,7 @@ static int at_dma_suspend_noirq(struct device *dev)
        struct dma_chan *chan, *_chan;
 
        /* preserve data */
-       list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+       list_for_each_entry_safe(chan, _chan, &atdma->dma_device.channels,
                        device_node) {
                struct at_dma_chan *atchan = to_at_dma_chan(chan);
 
@@ -2078,7 +2189,7 @@ static int at_dma_suspend_noirq(struct device *dev)
 
 static void atc_resume_cyclic(struct at_dma_chan *atchan)
 {
-       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
+       struct at_dma   *atdma = to_at_dma(atchan->vc.chan.device);
 
        /* restore channel status for cyclic descriptors list:
         * next descriptor in the cyclic list at the time of suspend */
@@ -2110,7 +2221,7 @@ static int at_dma_resume_noirq(struct device *dev)
 
        /* restore saved data */
        dma_writel(atdma, EBCIER, atdma->save_imr);
-       list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+       list_for_each_entry_safe(chan, _chan, &atdma->dma_device.channels,
                        device_node) {
                struct at_dma_chan *atchan = to_at_dma_chan(chan);
 
@@ -2121,7 +2232,7 @@ static int at_dma_resume_noirq(struct device *dev)
        return 0;
 }
 
-static const struct dev_pm_ops at_dma_dev_pm_ops = {
+static const struct dev_pm_ops __maybe_unused at_dma_dev_pm_ops = {
        .prepare = at_dma_prepare,
        .suspend_noirq = at_dma_suspend_noirq,
        .resume_noirq = at_dma_resume_noirq,
@@ -2133,7 +2244,7 @@ static struct platform_driver at_dma_driver = {
        .id_table       = atdma_devtypes,
        .driver = {
                .name   = "at_hdmac",
-               .pm     = &at_dma_dev_pm_ops,
+               .pm     = pm_ptr(&at_dma_dev_pm_ops),
                .of_match_table = of_match_ptr(atmel_dma_dt_ids),
        },
 };
@@ -2152,5 +2263,6 @@ module_exit(at_dma_exit);
 
 MODULE_DESCRIPTION("Atmel AHB DMA Controller driver");
 MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
+MODULE_AUTHOR("Tudor Ambarus <tudor.ambarus@microchip.com>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:at_hdmac");
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
deleted file mode 100644 (file)
index d4d382d..0000000
+++ /dev/null
@@ -1,478 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Header file for the Atmel AHB DMA Controller driver
- *
- * Copyright (C) 2008 Atmel Corporation
- */
-#ifndef AT_HDMAC_REGS_H
-#define        AT_HDMAC_REGS_H
-
-#define        AT_DMA_MAX_NR_CHANNELS  8
-
-
-#define        AT_DMA_GCFG     0x00    /* Global Configuration Register */
-#define                AT_DMA_IF_BIGEND(i)     (0x1 << (i))    /* AHB-Lite Interface i in Big-endian mode */
-#define                AT_DMA_ARB_CFG  (0x1 << 4)      /* Arbiter mode. */
-#define                        AT_DMA_ARB_CFG_FIXED            (0x0 << 4)
-#define                        AT_DMA_ARB_CFG_ROUND_ROBIN      (0x1 << 4)
-
-#define        AT_DMA_EN       0x04    /* Controller Enable Register */
-#define                AT_DMA_ENABLE   (0x1 << 0)
-
-#define        AT_DMA_SREQ     0x08    /* Software Single Request Register */
-#define                AT_DMA_SSREQ(x) (0x1 << ((x) << 1))             /* Request a source single transfer on channel x */
-#define                AT_DMA_DSREQ(x) (0x1 << (1 + ((x) << 1)))       /* Request a destination single transfer on channel x */
-
-#define        AT_DMA_CREQ     0x0C    /* Software Chunk Transfer Request Register */
-#define                AT_DMA_SCREQ(x) (0x1 << ((x) << 1))             /* Request a source chunk transfer on channel x */
-#define                AT_DMA_DCREQ(x) (0x1 << (1 + ((x) << 1)))       /* Request a destination chunk transfer on channel x */
-
-#define        AT_DMA_LAST     0x10    /* Software Last Transfer Flag Register */
-#define                AT_DMA_SLAST(x) (0x1 << ((x) << 1))             /* This src rq is last tx of buffer on channel x */
-#define                AT_DMA_DLAST(x) (0x1 << (1 + ((x) << 1)))       /* This dst rq is last tx of buffer on channel x */
-
-#define        AT_DMA_SYNC     0x14    /* Request Synchronization Register */
-#define                AT_DMA_SYR(h)   (0x1 << (h))                    /* Synchronize handshake line h */
-
-/* Error, Chained Buffer transfer completed and Buffer transfer completed Interrupt registers */
-#define        AT_DMA_EBCIER   0x18    /* Enable register */
-#define        AT_DMA_EBCIDR   0x1C    /* Disable register */
-#define        AT_DMA_EBCIMR   0x20    /* Mask Register */
-#define        AT_DMA_EBCISR   0x24    /* Status Register */
-#define                AT_DMA_CBTC_OFFSET      8
-#define                AT_DMA_ERR_OFFSET       16
-#define                AT_DMA_BTC(x)   (0x1 << (x))
-#define                AT_DMA_CBTC(x)  (0x1 << (AT_DMA_CBTC_OFFSET + (x)))
-#define                AT_DMA_ERR(x)   (0x1 << (AT_DMA_ERR_OFFSET + (x)))
-
-#define        AT_DMA_CHER     0x28    /* Channel Handler Enable Register */
-#define                AT_DMA_ENA(x)   (0x1 << (x))
-#define                AT_DMA_SUSP(x)  (0x1 << ( 8 + (x)))
-#define                AT_DMA_KEEP(x)  (0x1 << (24 + (x)))
-
-#define        AT_DMA_CHDR     0x2C    /* Channel Handler Disable Register */
-#define                AT_DMA_DIS(x)   (0x1 << (x))
-#define                AT_DMA_RES(x)   (0x1 << ( 8 + (x)))
-
-#define        AT_DMA_CHSR     0x30    /* Channel Handler Status Register */
-#define                AT_DMA_EMPT(x)  (0x1 << (16 + (x)))
-#define                AT_DMA_STAL(x)  (0x1 << (24 + (x)))
-
-
-#define        AT_DMA_CH_REGS_BASE     0x3C    /* Channel registers base address */
-#define        ch_regs(x)      (AT_DMA_CH_REGS_BASE + (x) * 0x28) /* Channel x base addr */
-
-/* Hardware register offset for each channel */
-#define        ATC_SADDR_OFFSET        0x00    /* Source Address Register */
-#define        ATC_DADDR_OFFSET        0x04    /* Destination Address Register */
-#define        ATC_DSCR_OFFSET         0x08    /* Descriptor Address Register */
-#define        ATC_CTRLA_OFFSET        0x0C    /* Control A Register */
-#define        ATC_CTRLB_OFFSET        0x10    /* Control B Register */
-#define        ATC_CFG_OFFSET          0x14    /* Configuration Register */
-#define        ATC_SPIP_OFFSET         0x18    /* Src PIP Configuration Register */
-#define        ATC_DPIP_OFFSET         0x1C    /* Dst PIP Configuration Register */
-
-
-/* Bitfield definitions */
-
-/* Bitfields in DSCR */
-#define        ATC_DSCR_IF(i)          (0x3 & (i))     /* Dsc feched via AHB-Lite Interface i */
-
-/* Bitfields in CTRLA */
-#define        ATC_BTSIZE_MAX          0xFFFFUL        /* Maximum Buffer Transfer Size */
-#define        ATC_BTSIZE(x)           (ATC_BTSIZE_MAX & (x)) /* Buffer Transfer Size */
-#define        ATC_SCSIZE_MASK         (0x7 << 16)     /* Source Chunk Transfer Size */
-#define                ATC_SCSIZE(x)           (ATC_SCSIZE_MASK & ((x) << 16))
-#define                ATC_SCSIZE_1            (0x0 << 16)
-#define                ATC_SCSIZE_4            (0x1 << 16)
-#define                ATC_SCSIZE_8            (0x2 << 16)
-#define                ATC_SCSIZE_16           (0x3 << 16)
-#define                ATC_SCSIZE_32           (0x4 << 16)
-#define                ATC_SCSIZE_64           (0x5 << 16)
-#define                ATC_SCSIZE_128          (0x6 << 16)
-#define                ATC_SCSIZE_256          (0x7 << 16)
-#define        ATC_DCSIZE_MASK         (0x7 << 20)     /* Destination Chunk Transfer Size */
-#define                ATC_DCSIZE(x)           (ATC_DCSIZE_MASK & ((x) << 20))
-#define                ATC_DCSIZE_1            (0x0 << 20)
-#define                ATC_DCSIZE_4            (0x1 << 20)
-#define                ATC_DCSIZE_8            (0x2 << 20)
-#define                ATC_DCSIZE_16           (0x3 << 20)
-#define                ATC_DCSIZE_32           (0x4 << 20)
-#define                ATC_DCSIZE_64           (0x5 << 20)
-#define                ATC_DCSIZE_128          (0x6 << 20)
-#define                ATC_DCSIZE_256          (0x7 << 20)
-#define        ATC_SRC_WIDTH_MASK      (0x3 << 24)     /* Source Single Transfer Size */
-#define                ATC_SRC_WIDTH(x)        ((x) << 24)
-#define                ATC_SRC_WIDTH_BYTE      (0x0 << 24)
-#define                ATC_SRC_WIDTH_HALFWORD  (0x1 << 24)
-#define                ATC_SRC_WIDTH_WORD      (0x2 << 24)
-#define                ATC_REG_TO_SRC_WIDTH(r) (((r) >> 24) & 0x3)
-#define        ATC_DST_WIDTH_MASK      (0x3 << 28)     /* Destination Single Transfer Size */
-#define                ATC_DST_WIDTH(x)        ((x) << 28)
-#define                ATC_DST_WIDTH_BYTE      (0x0 << 28)
-#define                ATC_DST_WIDTH_HALFWORD  (0x1 << 28)
-#define                ATC_DST_WIDTH_WORD      (0x2 << 28)
-#define        ATC_DONE                (0x1 << 31)     /* Tx Done (only written back in descriptor) */
-
-/* Bitfields in CTRLB */
-#define        ATC_SIF(i)              (0x3 & (i))     /* Src tx done via AHB-Lite Interface i */
-#define        ATC_DIF(i)              ((0x3 & (i)) <<  4)     /* Dst tx done via AHB-Lite Interface i */
-                                 /* Specify AHB interfaces */
-#define AT_DMA_MEM_IF          0 /* interface 0 as memory interface */
-#define AT_DMA_PER_IF          1 /* interface 1 as peripheral interface */
-
-#define        ATC_SRC_PIP             (0x1 <<  8)     /* Source Picture-in-Picture enabled */
-#define        ATC_DST_PIP             (0x1 << 12)     /* Destination Picture-in-Picture enabled */
-#define        ATC_SRC_DSCR_DIS        (0x1 << 16)     /* Src Descriptor fetch disable */
-#define        ATC_DST_DSCR_DIS        (0x1 << 20)     /* Dst Descriptor fetch disable */
-#define        ATC_FC_MASK             (0x7 << 21)     /* Choose Flow Controller */
-#define                ATC_FC_MEM2MEM          (0x0 << 21)     /* Mem-to-Mem (DMA) */
-#define                ATC_FC_MEM2PER          (0x1 << 21)     /* Mem-to-Periph (DMA) */
-#define                ATC_FC_PER2MEM          (0x2 << 21)     /* Periph-to-Mem (DMA) */
-#define                ATC_FC_PER2PER          (0x3 << 21)     /* Periph-to-Periph (DMA) */
-#define                ATC_FC_PER2MEM_PER      (0x4 << 21)     /* Periph-to-Mem (Peripheral) */
-#define                ATC_FC_MEM2PER_PER      (0x5 << 21)     /* Mem-to-Periph (Peripheral) */
-#define                ATC_FC_PER2PER_SRCPER   (0x6 << 21)     /* Periph-to-Periph (Src Peripheral) */
-#define                ATC_FC_PER2PER_DSTPER   (0x7 << 21)     /* Periph-to-Periph (Dst Peripheral) */
-#define        ATC_SRC_ADDR_MODE_MASK  (0x3 << 24)
-#define                ATC_SRC_ADDR_MODE_INCR  (0x0 << 24)     /* Incrementing Mode */
-#define                ATC_SRC_ADDR_MODE_DECR  (0x1 << 24)     /* Decrementing Mode */
-#define                ATC_SRC_ADDR_MODE_FIXED (0x2 << 24)     /* Fixed Mode */
-#define        ATC_DST_ADDR_MODE_MASK  (0x3 << 28)
-#define                ATC_DST_ADDR_MODE_INCR  (0x0 << 28)     /* Incrementing Mode */
-#define                ATC_DST_ADDR_MODE_DECR  (0x1 << 28)     /* Decrementing Mode */
-#define                ATC_DST_ADDR_MODE_FIXED (0x2 << 28)     /* Fixed Mode */
-#define        ATC_IEN                 (0x1 << 30)     /* BTC interrupt enable (active low) */
-#define        ATC_AUTO                (0x1 << 31)     /* Auto multiple buffer tx enable */
-
-/* Bitfields in CFG */
-#define ATC_PER_MSB(h) ((0x30U & (h)) >> 4)    /* Extract most significant bits of a handshaking identifier */
-
-#define        ATC_SRC_PER(h)          (0xFU & (h))    /* Channel src rq associated with periph handshaking ifc h */
-#define        ATC_DST_PER(h)          ((0xFU & (h)) <<  4)    /* Channel dst rq associated with periph handshaking ifc h */
-#define        ATC_SRC_REP             (0x1 <<  8)     /* Source Replay Mod */
-#define        ATC_SRC_H2SEL           (0x1 <<  9)     /* Source Handshaking Mod */
-#define                ATC_SRC_H2SEL_SW        (0x0 <<  9)
-#define                ATC_SRC_H2SEL_HW        (0x1 <<  9)
-#define        ATC_SRC_PER_MSB(h)      (ATC_PER_MSB(h) << 10)  /* Channel src rq (most significant bits) */
-#define        ATC_DST_REP             (0x1 << 12)     /* Destination Replay Mod */
-#define        ATC_DST_H2SEL           (0x1 << 13)     /* Destination Handshaking Mod */
-#define                ATC_DST_H2SEL_SW        (0x0 << 13)
-#define                ATC_DST_H2SEL_HW        (0x1 << 13)
-#define        ATC_DST_PER_MSB(h)      (ATC_PER_MSB(h) << 14)  /* Channel dst rq (most significant bits) */
-#define        ATC_SOD                 (0x1 << 16)     /* Stop On Done */
-#define        ATC_LOCK_IF             (0x1 << 20)     /* Interface Lock */
-#define        ATC_LOCK_B              (0x1 << 21)     /* AHB Bus Lock */
-#define        ATC_LOCK_IF_L           (0x1 << 22)     /* Master Interface Arbiter Lock */
-#define                ATC_LOCK_IF_L_CHUNK     (0x0 << 22)
-#define                ATC_LOCK_IF_L_BUFFER    (0x1 << 22)
-#define        ATC_AHB_PROT_MASK       (0x7 << 24)     /* AHB Protection */
-#define        ATC_FIFOCFG_MASK        (0x3 << 28)     /* FIFO Request Configuration */
-#define                ATC_FIFOCFG_LARGESTBURST        (0x0 << 28)
-#define                ATC_FIFOCFG_HALFFIFO            (0x1 << 28)
-#define                ATC_FIFOCFG_ENOUGHSPACE         (0x2 << 28)
-
-/* Bitfields in SPIP */
-#define        ATC_SPIP_HOLE(x)        (0xFFFFU & (x))
-#define        ATC_SPIP_BOUNDARY(x)    ((0x3FF & (x)) << 16)
-
-/* Bitfields in DPIP */
-#define        ATC_DPIP_HOLE(x)        (0xFFFFU & (x))
-#define        ATC_DPIP_BOUNDARY(x)    ((0x3FF & (x)) << 16)
-
-
-/*--  descriptors  -----------------------------------------------------*/
-
-/* LLI == Linked List Item; aka DMA buffer descriptor */
-struct at_lli {
-       /* values that are not changed by hardware */
-       u32 saddr;
-       u32 daddr;
-       /* value that may get written back: */
-       u32 ctrla;
-       /* more values that are not changed by hardware */
-       u32 ctrlb;
-       u32 dscr;       /* chain to next lli */
-};
-
-/**
- * struct at_desc - software descriptor
- * @at_lli: hardware lli structure
- * @txd: support for the async_tx api
- * @desc_node: node on the channed descriptors list
- * @len: descriptor byte count
- * @total_len: total transaction byte count
- */
-struct at_desc {
-       /* FIRST values the hardware uses */
-       struct at_lli                   lli;
-
-       /* THEN values for driver housekeeping */
-       struct list_head                tx_list;
-       struct dma_async_tx_descriptor  txd;
-       struct list_head                desc_node;
-       size_t                          len;
-       size_t                          total_len;
-
-       /* Interleaved data */
-       size_t                          boundary;
-       size_t                          dst_hole;
-       size_t                          src_hole;
-
-       /* Memset temporary buffer */
-       bool                            memset_buffer;
-       dma_addr_t                      memset_paddr;
-       int                             *memset_vaddr;
-};
-
-static inline struct at_desc *
-txd_to_at_desc(struct dma_async_tx_descriptor *txd)
-{
-       return container_of(txd, struct at_desc, txd);
-}
-
-
-/*--  Channels  --------------------------------------------------------*/
-
-/**
- * atc_status - information bits stored in channel status flag
- *
- * Manipulated with atomic operations.
- */
-enum atc_status {
-       ATC_IS_ERROR = 0,
-       ATC_IS_PAUSED = 1,
-       ATC_IS_CYCLIC = 24,
-};
-
-/**
- * struct at_dma_chan - internal representation of an Atmel HDMAC channel
- * @chan_common: common dmaengine channel object members
- * @device: parent device
- * @ch_regs: memory mapped register base
- * @mask: channel index in a mask
- * @per_if: peripheral interface
- * @mem_if: memory interface
- * @status: transmit status information from irq/prep* functions
- *                to tasklet (use atomic operations)
- * @tasklet: bottom half to finish transaction work
- * @save_cfg: configuration register that is saved on suspend/resume cycle
- * @save_dscr: for cyclic operations, preserve next descriptor address in
- *             the cyclic list on suspend/resume cycle
- * @dma_sconfig: configuration for slave transfers, passed via
- * .device_config
- * @lock: serializes enqueue/dequeue operations to descriptors lists
- * @active_list: list of descriptors dmaengine is being running on
- * @queue: list of descriptors ready to be submitted to engine
- * @free_list: list of descriptors usable by the channel
- */
-struct at_dma_chan {
-       struct dma_chan         chan_common;
-       struct at_dma           *device;
-       void __iomem            *ch_regs;
-       u8                      mask;
-       u8                      per_if;
-       u8                      mem_if;
-       unsigned long           status;
-       struct tasklet_struct   tasklet;
-       u32                     save_cfg;
-       u32                     save_dscr;
-       struct dma_slave_config dma_sconfig;
-
-       spinlock_t              lock;
-
-       /* these other elements are all protected by lock */
-       struct list_head        active_list;
-       struct list_head        queue;
-       struct list_head        free_list;
-};
-
-#define        channel_readl(atchan, name) \
-       __raw_readl((atchan)->ch_regs + ATC_##name##_OFFSET)
-
-#define        channel_writel(atchan, name, val) \
-       __raw_writel((val), (atchan)->ch_regs + ATC_##name##_OFFSET)
-
-static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
-{
-       return container_of(dchan, struct at_dma_chan, chan_common);
-}
-
-/*
- * Fix sconfig's burst size according to at_hdmac. We need to convert them as:
- * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3, 32 -> 4, 64 -> 5, 128 -> 6, 256 -> 7.
- *
- * This can be done by finding most significant bit set.
- */
-static inline void convert_burst(u32 *maxburst)
-{
-       if (*maxburst > 1)
-               *maxburst = fls(*maxburst) - 2;
-       else
-               *maxburst = 0;
-}
-
-/*
- * Fix sconfig's bus width according to at_hdmac.
- * 1 byte -> 0, 2 bytes -> 1, 4 bytes -> 2.
- */
-static inline u8 convert_buswidth(enum dma_slave_buswidth addr_width)
-{
-       switch (addr_width) {
-       case DMA_SLAVE_BUSWIDTH_2_BYTES:
-               return 1;
-       case DMA_SLAVE_BUSWIDTH_4_BYTES:
-               return 2;
-       default:
-               /* For 1 byte width or fallback */
-               return 0;
-       }
-}
-
-/*--  Controller  ------------------------------------------------------*/
-
-/**
- * struct at_dma - internal representation of an Atmel HDMA Controller
- * @chan_common: common dmaengine dma_device object members
- * @atdma_devtype: identifier of DMA controller compatibility
- * @ch_regs: memory mapped register base
- * @clk: dma controller clock
- * @save_imr: interrupt mask register that is saved on suspend/resume cycle
- * @all_chan_mask: all channels availlable in a mask
- * @dma_desc_pool: base of DMA descriptor region (DMA address)
- * @chan: channels table to store at_dma_chan structures
- */
-struct at_dma {
-       struct dma_device       dma_common;
-       void __iomem            *regs;
-       struct clk              *clk;
-       u32                     save_imr;
-
-       u8                      all_chan_mask;
-
-       struct dma_pool         *dma_desc_pool;
-       struct dma_pool         *memset_pool;
-       /* AT THE END channels table */
-       struct at_dma_chan      chan[];
-};
-
-#define        dma_readl(atdma, name) \
-       __raw_readl((atdma)->regs + AT_DMA_##name)
-#define        dma_writel(atdma, name, val) \
-       __raw_writel((val), (atdma)->regs + AT_DMA_##name)
-
-static inline struct at_dma *to_at_dma(struct dma_device *ddev)
-{
-       return container_of(ddev, struct at_dma, dma_common);
-}
-
-
-/*--  Helper functions  ------------------------------------------------*/
-
-static struct device *chan2dev(struct dma_chan *chan)
-{
-       return &chan->dev->device;
-}
-
-#if defined(VERBOSE_DEBUG)
-static void vdbg_dump_regs(struct at_dma_chan *atchan)
-{
-       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
-
-       dev_err(chan2dev(&atchan->chan_common),
-               "  channel %d : imr = 0x%x, chsr = 0x%x\n",
-               atchan->chan_common.chan_id,
-               dma_readl(atdma, EBCIMR),
-               dma_readl(atdma, CHSR));
-
-       dev_err(chan2dev(&atchan->chan_common),
-               "  channel: s0x%x d0x%x ctrl0x%x:0x%x cfg0x%x l0x%x\n",
-               channel_readl(atchan, SADDR),
-               channel_readl(atchan, DADDR),
-               channel_readl(atchan, CTRLA),
-               channel_readl(atchan, CTRLB),
-               channel_readl(atchan, CFG),
-               channel_readl(atchan, DSCR));
-}
-#else
-static void vdbg_dump_regs(struct at_dma_chan *atchan) {}
-#endif
-
-static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
-{
-       dev_crit(chan2dev(&atchan->chan_common),
-                "desc: s%pad d%pad ctrl0x%x:0x%x l%pad\n",
-                &lli->saddr, &lli->daddr,
-                lli->ctrla, lli->ctrlb, &lli->dscr);
-}
-
-
-static void atc_setup_irq(struct at_dma *atdma, int chan_id, int on)
-{
-       u32 ebci;
-
-       /* enable interrupts on buffer transfer completion & error */
-       ebci =    AT_DMA_BTC(chan_id)
-               | AT_DMA_ERR(chan_id);
-       if (on)
-               dma_writel(atdma, EBCIER, ebci);
-       else
-               dma_writel(atdma, EBCIDR, ebci);
-}
-
-static void atc_enable_chan_irq(struct at_dma *atdma, int chan_id)
-{
-       atc_setup_irq(atdma, chan_id, 1);
-}
-
-static void atc_disable_chan_irq(struct at_dma *atdma, int chan_id)
-{
-       atc_setup_irq(atdma, chan_id, 0);
-}
-
-
-/**
- * atc_chan_is_enabled - test if given channel is enabled
- * @atchan: channel we want to test status
- */
-static inline int atc_chan_is_enabled(struct at_dma_chan *atchan)
-{
-       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
-
-       return !!(dma_readl(atdma, CHSR) & atchan->mask);
-}
-
-/**
- * atc_chan_is_paused - test channel pause/resume status
- * @atchan: channel we want to test status
- */
-static inline int atc_chan_is_paused(struct at_dma_chan *atchan)
-{
-       return test_bit(ATC_IS_PAUSED, &atchan->status);
-}
-
-/**
- * atc_chan_is_cyclic - test if given channel has cyclic property set
- * @atchan: channel we want to test status
- */
-static inline int atc_chan_is_cyclic(struct at_dma_chan *atchan)
-{
-       return test_bit(ATC_IS_CYCLIC, &atchan->status);
-}
-
-/**
- * set_desc_eol - set end-of-link to descriptor so it will end transfer
- * @desc: descriptor, signle or at the end of a chain, to end chain on
- */
-static void set_desc_eol(struct at_desc *desc)
-{
-       u32 ctrlb = desc->lli.ctrlb;
-
-       ctrlb &= ~ATC_IEN;
-       ctrlb |= ATC_SRC_DSCR_DIS | ATC_DST_DSCR_DIS;
-
-       desc->lli.ctrlb = ctrlb;
-       desc->lli.dscr = 0;
-}
-
-#endif /* AT_HDMAC_REGS_H */
index 2a483802d9eeb476d414bf737ae6da166c4c3fc3..9c1a6e9a9c03084d622daef7d19bbd8955254547 100644 (file)
@@ -1038,6 +1038,13 @@ static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = {
                 JZ_SOC_DATA_BREAK_LINKS,
 };
 
+static const struct jz4780_dma_soc_data jz4755_dma_soc_data = {
+       .nb_channels = 4,
+       .transfer_ord_max = 5,
+       .flags = JZ_SOC_DATA_PER_CHAN_PM | JZ_SOC_DATA_NO_DCKES_DCKEC |
+                JZ_SOC_DATA_BREAK_LINKS,
+};
+
 static const struct jz4780_dma_soc_data jz4760_dma_soc_data = {
        .nb_channels = 5,
        .transfer_ord_max = 6,
@@ -1101,6 +1108,7 @@ static const struct jz4780_dma_soc_data x1830_dma_soc_data = {
 static const struct of_device_id jz4780_dma_dt_match[] = {
        { .compatible = "ingenic,jz4740-dma", .data = &jz4740_dma_soc_data },
        { .compatible = "ingenic,jz4725b-dma", .data = &jz4725b_dma_soc_data },
+       { .compatible = "ingenic,jz4755-dma", .data = &jz4755_dma_soc_data },
        { .compatible = "ingenic,jz4760-dma", .data = &jz4760_dma_soc_data },
        { .compatible = "ingenic,jz4760-mdma", .data = &jz4760_mdma_soc_data },
        { .compatible = "ingenic,jz4760-bdma", .data = &jz4760_bdma_soc_data },
index f4c07ad3be15b427a43b7c9a60e4e5d43f9a9fa2..c33087c5cd0214f23f5f595c86bedf1371f4912f 100644 (file)
@@ -600,7 +600,7 @@ static int idma64_probe(struct idma64_chip *chip)
        return 0;
 }
 
-static int idma64_remove(struct idma64_chip *chip)
+static void idma64_remove(struct idma64_chip *chip)
 {
        struct idma64 *idma64 = chip->idma64;
        unsigned short i;
@@ -618,8 +618,6 @@ static int idma64_remove(struct idma64_chip *chip)
 
                tasklet_kill(&idma64c->vchan.task);
        }
-
-       return 0;
 }
 
 /* ---------------------------------------------------------------------- */
@@ -664,7 +662,9 @@ static int idma64_platform_remove(struct platform_device *pdev)
 {
        struct idma64_chip *chip = platform_get_drvdata(pdev);
 
-       return idma64_remove(chip);
+       idma64_remove(chip);
+
+       return 0;
 }
 
 static int __maybe_unused idma64_pm_suspend(struct device *dev)
index 6f44fa8f78a5d330d1c8239706df6b9a3474d559..06f5d3783d7719e01ad896818f5fa48a75cf945e 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/dmaengine.h>
 #include <linux/irq.h>
-#include <linux/msi.h>
 #include <uapi/linux/idxd.h>
 #include "../dmaengine.h"
 #include "idxd.h"
index 7269bd54554f60cb5b8915c9a1ed7f2a36ba66bf..3229dfc78650784733a261fa539e6de64bf1979d 100644 (file)
@@ -528,6 +528,22 @@ static bool idxd_group_attr_progress_limit_invisible(struct attribute *attr,
                !idxd->hw.group_cap.progress_limit;
 }
 
+static bool idxd_group_attr_read_buffers_invisible(struct attribute *attr,
+                                                  struct idxd_device *idxd)
+{
+       /*
+        * Intel IAA does not support Read Buffer allocation control,
+        * make these attributes invisible.
+        */
+       return (attr == &dev_attr_group_use_token_limit.attr ||
+               attr == &dev_attr_group_use_read_buffer_limit.attr ||
+               attr == &dev_attr_group_tokens_allowed.attr ||
+               attr == &dev_attr_group_read_buffers_allowed.attr ||
+               attr == &dev_attr_group_tokens_reserved.attr ||
+               attr == &dev_attr_group_read_buffers_reserved.attr) &&
+               idxd->data->type == IDXD_TYPE_IAX;
+}
+
 static umode_t idxd_group_attr_visible(struct kobject *kobj,
                                       struct attribute *attr, int n)
 {
@@ -538,6 +554,9 @@ static umode_t idxd_group_attr_visible(struct kobject *kobj,
        if (idxd_group_attr_progress_limit_invisible(attr, idxd))
                return 0;
 
+       if (idxd_group_attr_read_buffers_invisible(attr, idxd))
+               return 0;
+
        return attr->mode;
 }
 
@@ -1233,6 +1252,14 @@ static bool idxd_wq_attr_op_config_invisible(struct attribute *attr,
               !idxd->hw.wq_cap.op_config;
 }
 
+static bool idxd_wq_attr_max_batch_size_invisible(struct attribute *attr,
+                                                 struct idxd_device *idxd)
+{
+       /* Intel IAA does not support batch processing, make it invisible */
+       return attr == &dev_attr_wq_max_batch_size.attr &&
+              idxd->data->type == IDXD_TYPE_IAX;
+}
+
 static umode_t idxd_wq_attr_visible(struct kobject *kobj,
                                    struct attribute *attr, int n)
 {
@@ -1243,6 +1270,9 @@ static umode_t idxd_wq_attr_visible(struct kobject *kobj,
        if (idxd_wq_attr_op_config_invisible(attr, idxd))
                return 0;
 
+       if (idxd_wq_attr_max_batch_size_invisible(attr, idxd))
+               return 0;
+
        return attr->mode;
 }
 
@@ -1533,6 +1563,43 @@ static ssize_t cmd_status_store(struct device *dev, struct device_attribute *att
 }
 static DEVICE_ATTR_RW(cmd_status);
 
+static bool idxd_device_attr_max_batch_size_invisible(struct attribute *attr,
+                                                     struct idxd_device *idxd)
+{
+       /* Intel IAA does not support batch processing, make it invisible */
+       return attr == &dev_attr_max_batch_size.attr &&
+              idxd->data->type == IDXD_TYPE_IAX;
+}
+
+static bool idxd_device_attr_read_buffers_invisible(struct attribute *attr,
+                                                   struct idxd_device *idxd)
+{
+       /*
+        * Intel IAA does not support Read Buffer allocation control,
+        * make these attributes invisible.
+        */
+       return (attr == &dev_attr_max_tokens.attr ||
+               attr == &dev_attr_max_read_buffers.attr ||
+               attr == &dev_attr_token_limit.attr ||
+               attr == &dev_attr_read_buffer_limit.attr) &&
+               idxd->data->type == IDXD_TYPE_IAX;
+}
+
+static umode_t idxd_device_attr_visible(struct kobject *kobj,
+                                       struct attribute *attr, int n)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct idxd_device *idxd = confdev_to_idxd(dev);
+
+       if (idxd_device_attr_max_batch_size_invisible(attr, idxd))
+               return 0;
+
+       if (idxd_device_attr_read_buffers_invisible(attr, idxd))
+               return 0;
+
+       return attr->mode;
+}
+
 static struct attribute *idxd_device_attributes[] = {
        &dev_attr_version.attr,
        &dev_attr_max_groups.attr,
@@ -1560,6 +1627,7 @@ static struct attribute *idxd_device_attributes[] = {
 
 static const struct attribute_group idxd_device_attribute_group = {
        .attrs = idxd_device_attributes,
+       .is_visible = idxd_device_attr_visible,
 };
 
 static const struct attribute_group *idxd_attribute_groups[] = {
index e2070df6cad287bda75386961060339eb1b15d30..79d244011093cfb95e6195d0bfde045bcea3c8de 100644 (file)
@@ -33,7 +33,7 @@ MODULE_PARM_DESC(completion_timeout,
 static int idle_timeout = 2000;
 module_param(idle_timeout, int, 0644);
 MODULE_PARM_DESC(idle_timeout,
-               "set ioat idel timeout [msec] (default 2000 [msec])");
+               "set ioat idle timeout [msec] (default 2000 [msec])");
 
 #define IDLE_TIMEOUT msecs_to_jiffies(idle_timeout)
 #define COMPLETION_TIMEOUT msecs_to_jiffies(completion_timeout)
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
deleted file mode 100644 (file)
index 310b899..0000000
+++ /dev/null
@@ -1,1554 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * offload engine driver for the Intel Xscale series of i/o processors
- * Copyright Â© 2006, Intel Corporation.
- */
-
-/*
- * This driver supports the asynchrounous DMA copy and RAID engines available
- * on the Intel Xscale(R) family of I/O Processors (IOP 32x, 33x, 134x)
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/prefetch.h>
-#include <linux/memory.h>
-#include <linux/ioport.h>
-#include <linux/raid/pq.h>
-#include <linux/slab.h>
-
-#include "iop-adma.h"
-#include "dmaengine.h"
-
-#define to_iop_adma_chan(chan) container_of(chan, struct iop_adma_chan, common)
-#define to_iop_adma_device(dev) \
-       container_of(dev, struct iop_adma_device, common)
-#define tx_to_iop_adma_slot(tx) \
-       container_of(tx, struct iop_adma_desc_slot, async_tx)
-
-/**
- * iop_adma_free_slots - flags descriptor slots for reuse
- * @slot: Slot to free
- * Caller must hold &iop_chan->lock while calling this function
- */
-static void iop_adma_free_slots(struct iop_adma_desc_slot *slot)
-{
-       int stride = slot->slots_per_op;
-
-       while (stride--) {
-               slot->slots_per_op = 0;
-               slot = list_entry(slot->slot_node.next,
-                               struct iop_adma_desc_slot,
-                               slot_node);
-       }
-}
-
-static dma_cookie_t
-iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
-       struct iop_adma_chan *iop_chan, dma_cookie_t cookie)
-{
-       struct dma_async_tx_descriptor *tx = &desc->async_tx;
-
-       BUG_ON(tx->cookie < 0);
-       if (tx->cookie > 0) {
-               cookie = tx->cookie;
-               tx->cookie = 0;
-
-               /* call the callback (must not sleep or submit new
-                * operations to this channel)
-                */
-               dmaengine_desc_get_callback_invoke(tx, NULL);
-
-               dma_descriptor_unmap(tx);
-               if (desc->group_head)
-                       desc->group_head = NULL;
-       }
-
-       /* run dependent operations */
-       dma_run_dependencies(tx);
-
-       return cookie;
-}
-
-static int
-iop_adma_clean_slot(struct iop_adma_desc_slot *desc,
-       struct iop_adma_chan *iop_chan)
-{
-       /* the client is allowed to attach dependent operations
-        * until 'ack' is set
-        */
-       if (!async_tx_test_ack(&desc->async_tx))
-               return 0;
-
-       /* leave the last descriptor in the chain
-        * so we can append to it
-        */
-       if (desc->chain_node.next == &iop_chan->chain)
-               return 1;
-
-       dev_dbg(iop_chan->device->common.dev,
-               "\tfree slot: %d slots_per_op: %d\n",
-               desc->idx, desc->slots_per_op);
-
-       list_del(&desc->chain_node);
-       iop_adma_free_slots(desc);
-
-       return 0;
-}
-
-static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
-{
-       struct iop_adma_desc_slot *iter, *_iter, *grp_start = NULL;
-       dma_cookie_t cookie = 0;
-       u32 current_desc = iop_chan_get_current_descriptor(iop_chan);
-       int busy = iop_chan_is_busy(iop_chan);
-       int seen_current = 0, slot_cnt = 0, slots_per_op = 0;
-
-       dev_dbg(iop_chan->device->common.dev, "%s\n", __func__);
-       /* free completed slots from the chain starting with
-        * the oldest descriptor
-        */
-       list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
-                                       chain_node) {
-               pr_debug("\tcookie: %d slot: %d busy: %d "
-                       "this_desc: %pad next_desc: %#llx ack: %d\n",
-                       iter->async_tx.cookie, iter->idx, busy,
-                       &iter->async_tx.phys, (u64)iop_desc_get_next_desc(iter),
-                       async_tx_test_ack(&iter->async_tx));
-               prefetch(_iter);
-               prefetch(&_iter->async_tx);
-
-               /* do not advance past the current descriptor loaded into the
-                * hardware channel, subsequent descriptors are either in
-                * process or have not been submitted
-                */
-               if (seen_current)
-                       break;
-
-               /* stop the search if we reach the current descriptor and the
-                * channel is busy, or if it appears that the current descriptor
-                * needs to be re-read (i.e. has been appended to)
-                */
-               if (iter->async_tx.phys == current_desc) {
-                       BUG_ON(seen_current++);
-                       if (busy || iop_desc_get_next_desc(iter))
-                               break;
-               }
-
-               /* detect the start of a group transaction */
-               if (!slot_cnt && !slots_per_op) {
-                       slot_cnt = iter->slot_cnt;
-                       slots_per_op = iter->slots_per_op;
-                       if (slot_cnt <= slots_per_op) {
-                               slot_cnt = 0;
-                               slots_per_op = 0;
-                       }
-               }
-
-               if (slot_cnt) {
-                       pr_debug("\tgroup++\n");
-                       if (!grp_start)
-                               grp_start = iter;
-                       slot_cnt -= slots_per_op;
-               }
-
-               /* all the members of a group are complete */
-               if (slots_per_op != 0 && slot_cnt == 0) {
-                       struct iop_adma_desc_slot *grp_iter, *_grp_iter;
-                       int end_of_chain = 0;
-                       pr_debug("\tgroup end\n");
-
-                       /* collect the total results */
-                       if (grp_start->xor_check_result) {
-                               u32 zero_sum_result = 0;
-                               slot_cnt = grp_start->slot_cnt;
-                               grp_iter = grp_start;
-
-                               list_for_each_entry_from(grp_iter,
-                                       &iop_chan->chain, chain_node) {
-                                       zero_sum_result |=
-                                           iop_desc_get_zero_result(grp_iter);
-                                       pr_debug("\titer%d result: %d\n",
-                                           grp_iter->idx, zero_sum_result);
-                                       slot_cnt -= slots_per_op;
-                                       if (slot_cnt == 0)
-                                               break;
-                               }
-                               pr_debug("\tgrp_start->xor_check_result: %p\n",
-                                       grp_start->xor_check_result);
-                               *grp_start->xor_check_result = zero_sum_result;
-                       }
-
-                       /* clean up the group */
-                       slot_cnt = grp_start->slot_cnt;
-                       grp_iter = grp_start;
-                       list_for_each_entry_safe_from(grp_iter, _grp_iter,
-                               &iop_chan->chain, chain_node) {
-                               cookie = iop_adma_run_tx_complete_actions(
-                                       grp_iter, iop_chan, cookie);
-
-                               slot_cnt -= slots_per_op;
-                               end_of_chain = iop_adma_clean_slot(grp_iter,
-                                       iop_chan);
-
-                               if (slot_cnt == 0 || end_of_chain)
-                                       break;
-                       }
-
-                       /* the group should be complete at this point */
-                       BUG_ON(slot_cnt);
-
-                       slots_per_op = 0;
-                       grp_start = NULL;
-                       if (end_of_chain)
-                               break;
-                       else
-                               continue;
-               } else if (slots_per_op) /* wait for group completion */
-                       continue;
-
-               /* write back zero sum results (single descriptor case) */
-               if (iter->xor_check_result && iter->async_tx.cookie)
-                       *iter->xor_check_result =
-                               iop_desc_get_zero_result(iter);
-
-               cookie = iop_adma_run_tx_complete_actions(
-                                       iter, iop_chan, cookie);
-
-               if (iop_adma_clean_slot(iter, iop_chan))
-                       break;
-       }
-
-       if (cookie > 0) {
-               iop_chan->common.completed_cookie = cookie;
-               pr_debug("\tcompleted cookie %d\n", cookie);
-       }
-}
-
-static void
-iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
-{
-       spin_lock_bh(&iop_chan->lock);
-       __iop_adma_slot_cleanup(iop_chan);
-       spin_unlock_bh(&iop_chan->lock);
-}
-
-static void iop_adma_tasklet(struct tasklet_struct *t)
-{
-       struct iop_adma_chan *iop_chan = from_tasklet(iop_chan, t,
-                                                     irq_tasklet);
-
-       /* lockdep will flag depedency submissions as potentially
-        * recursive locking, this is not the case as a dependency
-        * submission will never recurse a channels submit routine.
-        * There are checks in async_tx.c to prevent this.
-        */
-       spin_lock_nested(&iop_chan->lock, SINGLE_DEPTH_NESTING);
-       __iop_adma_slot_cleanup(iop_chan);
-       spin_unlock(&iop_chan->lock);
-}
-
-static struct iop_adma_desc_slot *
-iop_adma_alloc_slots(struct iop_adma_chan *iop_chan, int num_slots,
-                       int slots_per_op)
-{
-       struct iop_adma_desc_slot *iter, *_iter, *alloc_start = NULL;
-       LIST_HEAD(chain);
-       int slots_found, retry = 0;
-
-       /* start search from the last allocated descrtiptor
-        * if a contiguous allocation can not be found start searching
-        * from the beginning of the list
-        */
-retry:
-       slots_found = 0;
-       if (retry == 0)
-               iter = iop_chan->last_used;
-       else
-               iter = list_entry(&iop_chan->all_slots,
-                       struct iop_adma_desc_slot,
-                       slot_node);
-
-       list_for_each_entry_safe_continue(
-               iter, _iter, &iop_chan->all_slots, slot_node) {
-               prefetch(_iter);
-               prefetch(&_iter->async_tx);
-               if (iter->slots_per_op) {
-                       /* give up after finding the first busy slot
-                        * on the second pass through the list
-                        */
-                       if (retry)
-                               break;
-
-                       slots_found = 0;
-                       continue;
-               }
-
-               /* start the allocation if the slot is correctly aligned */
-               if (!slots_found++) {
-                       if (iop_desc_is_aligned(iter, slots_per_op))
-                               alloc_start = iter;
-                       else {
-                               slots_found = 0;
-                               continue;
-                       }
-               }
-
-               if (slots_found == num_slots) {
-                       struct iop_adma_desc_slot *alloc_tail = NULL;
-                       struct iop_adma_desc_slot *last_used = NULL;
-                       iter = alloc_start;
-                       while (num_slots) {
-                               int i;
-                               dev_dbg(iop_chan->device->common.dev,
-                                       "allocated slot: %d "
-                                       "(desc %p phys: %#llx) slots_per_op %d\n",
-                                       iter->idx, iter->hw_desc,
-                                       (u64)iter->async_tx.phys, slots_per_op);
-
-                               /* pre-ack all but the last descriptor */
-                               if (num_slots != slots_per_op)
-                                       async_tx_ack(&iter->async_tx);
-
-                               list_add_tail(&iter->chain_node, &chain);
-                               alloc_tail = iter;
-                               iter->async_tx.cookie = 0;
-                               iter->slot_cnt = num_slots;
-                               iter->xor_check_result = NULL;
-                               for (i = 0; i < slots_per_op; i++) {
-                                       iter->slots_per_op = slots_per_op - i;
-                                       last_used = iter;
-                                       iter = list_entry(iter->slot_node.next,
-                                               struct iop_adma_desc_slot,
-                                               slot_node);
-                               }
-                               num_slots -= slots_per_op;
-                       }
-                       alloc_tail->group_head = alloc_start;
-                       alloc_tail->async_tx.cookie = -EBUSY;
-                       list_splice(&chain, &alloc_tail->tx_list);
-                       iop_chan->last_used = last_used;
-                       iop_desc_clear_next_desc(alloc_start);
-                       iop_desc_clear_next_desc(alloc_tail);
-                       return alloc_tail;
-               }
-       }
-       if (!retry++)
-               goto retry;
-
-       /* perform direct reclaim if the allocation fails */
-       __iop_adma_slot_cleanup(iop_chan);
-
-       return NULL;
-}
-
-static void iop_adma_check_threshold(struct iop_adma_chan *iop_chan)
-{
-       dev_dbg(iop_chan->device->common.dev, "pending: %d\n",
-               iop_chan->pending);
-
-       if (iop_chan->pending >= IOP_ADMA_THRESHOLD) {
-               iop_chan->pending = 0;
-               iop_chan_append(iop_chan);
-       }
-}
-
-static dma_cookie_t
-iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
-{
-       struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
-       struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
-       struct iop_adma_desc_slot *grp_start, *old_chain_tail;
-       int slot_cnt;
-       dma_cookie_t cookie;
-       dma_addr_t next_dma;
-
-       grp_start = sw_desc->group_head;
-       slot_cnt = grp_start->slot_cnt;
-
-       spin_lock_bh(&iop_chan->lock);
-       cookie = dma_cookie_assign(tx);
-
-       old_chain_tail = list_entry(iop_chan->chain.prev,
-               struct iop_adma_desc_slot, chain_node);
-       list_splice_init(&sw_desc->tx_list,
-                        &old_chain_tail->chain_node);
-
-       /* fix up the hardware chain */
-       next_dma = grp_start->async_tx.phys;
-       iop_desc_set_next_desc(old_chain_tail, next_dma);
-       BUG_ON(iop_desc_get_next_desc(old_chain_tail) != next_dma); /* flush */
-
-       /* check for pre-chained descriptors */
-       iop_paranoia(iop_desc_get_next_desc(sw_desc));
-
-       /* increment the pending count by the number of slots
-        * memcpy operations have a 1:1 (slot:operation) relation
-        * other operations are heavier and will pop the threshold
-        * more often.
-        */
-       iop_chan->pending += slot_cnt;
-       iop_adma_check_threshold(iop_chan);
-       spin_unlock_bh(&iop_chan->lock);
-
-       dev_dbg(iop_chan->device->common.dev, "%s cookie: %d slot: %d\n",
-               __func__, sw_desc->async_tx.cookie, sw_desc->idx);
-
-       return cookie;
-}
-
-static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan);
-static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan);
-
-/**
- * iop_adma_alloc_chan_resources -  returns the number of allocated descriptors
- * @chan: allocate descriptor resources for this channel
- *
- * Note: We keep the slots for 1 operation on iop_chan->chain at all times.  To
- * avoid deadlock, via async_xor, num_descs_in_pool must at a minimum be
- * greater than 2x the number slots needed to satisfy a device->max_xor
- * request.
- * */
-static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
-{
-       char *hw_desc;
-       dma_addr_t dma_desc;
-       int idx;
-       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-       struct iop_adma_desc_slot *slot = NULL;
-       int init = iop_chan->slots_allocated ? 0 : 1;
-       struct iop_adma_platform_data *plat_data =
-               dev_get_platdata(&iop_chan->device->pdev->dev);
-       int num_descs_in_pool = plat_data->pool_size/IOP_ADMA_SLOT_SIZE;
-
-       /* Allocate descriptor slots */
-       do {
-               idx = iop_chan->slots_allocated;
-               if (idx == num_descs_in_pool)
-                       break;
-
-               slot = kzalloc(sizeof(*slot), GFP_KERNEL);
-               if (!slot) {
-                       printk(KERN_INFO "IOP ADMA Channel only initialized"
-                               " %d descriptor slots", idx);
-                       break;
-               }
-               hw_desc = (char *) iop_chan->device->dma_desc_pool_virt;
-               slot->hw_desc = (void *) &hw_desc[idx * IOP_ADMA_SLOT_SIZE];
-
-               dma_async_tx_descriptor_init(&slot->async_tx, chan);
-               slot->async_tx.tx_submit = iop_adma_tx_submit;
-               INIT_LIST_HEAD(&slot->tx_list);
-               INIT_LIST_HEAD(&slot->chain_node);
-               INIT_LIST_HEAD(&slot->slot_node);
-               dma_desc = iop_chan->device->dma_desc_pool;
-               slot->async_tx.phys = dma_desc + idx * IOP_ADMA_SLOT_SIZE;
-               slot->idx = idx;
-
-               spin_lock_bh(&iop_chan->lock);
-               iop_chan->slots_allocated++;
-               list_add_tail(&slot->slot_node, &iop_chan->all_slots);
-               spin_unlock_bh(&iop_chan->lock);
-       } while (iop_chan->slots_allocated < num_descs_in_pool);
-
-       if (idx && !iop_chan->last_used)
-               iop_chan->last_used = list_entry(iop_chan->all_slots.next,
-                                       struct iop_adma_desc_slot,
-                                       slot_node);
-
-       dev_dbg(iop_chan->device->common.dev,
-               "allocated %d descriptor slots last_used: %p\n",
-               iop_chan->slots_allocated, iop_chan->last_used);
-
-       /* initialize the channel and the chain with a null operation */
-       if (init) {
-               if (dma_has_cap(DMA_MEMCPY,
-                       iop_chan->device->common.cap_mask))
-                       iop_chan_start_null_memcpy(iop_chan);
-               else if (dma_has_cap(DMA_XOR,
-                       iop_chan->device->common.cap_mask))
-                       iop_chan_start_null_xor(iop_chan);
-               else
-                       BUG();
-       }
-
-       return (idx > 0) ? idx : -ENOMEM;
-}
-
-static struct dma_async_tx_descriptor *
-iop_adma_prep_dma_interrupt(struct dma_chan *chan, unsigned long flags)
-{
-       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-       struct iop_adma_desc_slot *sw_desc, *grp_start;
-       int slot_cnt, slots_per_op;
-
-       dev_dbg(iop_chan->device->common.dev, "%s\n", __func__);
-
-       spin_lock_bh(&iop_chan->lock);
-       slot_cnt = iop_chan_interrupt_slot_count(&slots_per_op, iop_chan);
-       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-       if (sw_desc) {
-               grp_start = sw_desc->group_head;
-               iop_desc_init_interrupt(grp_start, iop_chan);
-               sw_desc->async_tx.flags = flags;
-       }
-       spin_unlock_bh(&iop_chan->lock);
-
-       return sw_desc ? &sw_desc->async_tx : NULL;
-}
-
-static struct dma_async_tx_descriptor *
-iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
-                        dma_addr_t dma_src, size_t len, unsigned long flags)
-{
-       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-       struct iop_adma_desc_slot *sw_desc, *grp_start;
-       int slot_cnt, slots_per_op;
-
-       if (unlikely(!len))
-               return NULL;
-       BUG_ON(len > IOP_ADMA_MAX_BYTE_COUNT);
-
-       dev_dbg(iop_chan->device->common.dev, "%s len: %zu\n",
-               __func__, len);
-
-       spin_lock_bh(&iop_chan->lock);
-       slot_cnt = iop_chan_memcpy_slot_count(len, &slots_per_op);
-       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-       if (sw_desc) {
-               grp_start = sw_desc->group_head;
-               iop_desc_init_memcpy(grp_start, flags);
-               iop_desc_set_byte_count(grp_start, iop_chan, len);
-               iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
-               iop_desc_set_memcpy_src_addr(grp_start, dma_src);
-               sw_desc->async_tx.flags = flags;
-       }
-       spin_unlock_bh(&iop_chan->lock);
-
-       return sw_desc ? &sw_desc->async_tx : NULL;
-}
-
-static struct dma_async_tx_descriptor *
-iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest,
-                     dma_addr_t *dma_src, unsigned int src_cnt, size_t len,
-                     unsigned long flags)
-{
-       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-       struct iop_adma_desc_slot *sw_desc, *grp_start;
-       int slot_cnt, slots_per_op;
-
-       if (unlikely(!len))
-               return NULL;
-       BUG_ON(len > IOP_ADMA_XOR_MAX_BYTE_COUNT);
-
-       dev_dbg(iop_chan->device->common.dev,
-               "%s src_cnt: %d len: %zu flags: %lx\n",
-               __func__, src_cnt, len, flags);
-
-       spin_lock_bh(&iop_chan->lock);
-       slot_cnt = iop_chan_xor_slot_count(len, src_cnt, &slots_per_op);
-       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-       if (sw_desc) {
-               grp_start = sw_desc->group_head;
-               iop_desc_init_xor(grp_start, src_cnt, flags);
-               iop_desc_set_byte_count(grp_start, iop_chan, len);
-               iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
-               sw_desc->async_tx.flags = flags;
-               while (src_cnt--)
-                       iop_desc_set_xor_src_addr(grp_start, src_cnt,
-                                                 dma_src[src_cnt]);
-       }
-       spin_unlock_bh(&iop_chan->lock);
-
-       return sw_desc ? &sw_desc->async_tx : NULL;
-}
-
-static struct dma_async_tx_descriptor *
-iop_adma_prep_dma_xor_val(struct dma_chan *chan, dma_addr_t *dma_src,
-                         unsigned int src_cnt, size_t len, u32 *result,
-                         unsigned long flags)
-{
-       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-       struct iop_adma_desc_slot *sw_desc, *grp_start;
-       int slot_cnt, slots_per_op;
-
-       if (unlikely(!len))
-               return NULL;
-
-       dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %zu\n",
-               __func__, src_cnt, len);
-
-       spin_lock_bh(&iop_chan->lock);
-       slot_cnt = iop_chan_zero_sum_slot_count(len, src_cnt, &slots_per_op);
-       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-       if (sw_desc) {
-               grp_start = sw_desc->group_head;
-               iop_desc_init_zero_sum(grp_start, src_cnt, flags);
-               iop_desc_set_zero_sum_byte_count(grp_start, len);
-               grp_start->xor_check_result = result;
-               pr_debug("\t%s: grp_start->xor_check_result: %p\n",
-                       __func__, grp_start->xor_check_result);
-               sw_desc->async_tx.flags = flags;
-               while (src_cnt--)
-                       iop_desc_set_zero_sum_src_addr(grp_start, src_cnt,
-                                                      dma_src[src_cnt]);
-       }
-       spin_unlock_bh(&iop_chan->lock);
-
-       return sw_desc ? &sw_desc->async_tx : NULL;
-}
-
-static struct dma_async_tx_descriptor *
-iop_adma_prep_dma_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
-                    unsigned int src_cnt, const unsigned char *scf, size_t len,
-                    unsigned long flags)
-{
-       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-       struct iop_adma_desc_slot *sw_desc, *g;
-       int slot_cnt, slots_per_op;
-       int continue_srcs;
-
-       if (unlikely(!len))
-               return NULL;
-       BUG_ON(len > IOP_ADMA_XOR_MAX_BYTE_COUNT);
-
-       dev_dbg(iop_chan->device->common.dev,
-               "%s src_cnt: %d len: %zu flags: %lx\n",
-               __func__, src_cnt, len, flags);
-
-       if (dmaf_p_disabled_continue(flags))
-               continue_srcs = 1+src_cnt;
-       else if (dmaf_continue(flags))
-               continue_srcs = 3+src_cnt;
-       else
-               continue_srcs = 0+src_cnt;
-
-       spin_lock_bh(&iop_chan->lock);
-       slot_cnt = iop_chan_pq_slot_count(len, continue_srcs, &slots_per_op);
-       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-       if (sw_desc) {
-               int i;
-
-               g = sw_desc->group_head;
-               iop_desc_set_byte_count(g, iop_chan, len);
-
-               /* even if P is disabled its destination address (bits
-                * [3:0]) must match Q.  It is ok if P points to an
-                * invalid address, it won't be written.
-                */
-               if (flags & DMA_PREP_PQ_DISABLE_P)
-                       dst[0] = dst[1] & 0x7;
-
-               iop_desc_set_pq_addr(g, dst);
-               sw_desc->async_tx.flags = flags;
-               for (i = 0; i < src_cnt; i++)
-                       iop_desc_set_pq_src_addr(g, i, src[i], scf[i]);
-
-               /* if we are continuing a previous operation factor in
-                * the old p and q values, see the comment for dma_maxpq
-                * in include/linux/dmaengine.h
-                */
-               if (dmaf_p_disabled_continue(flags))
-                       iop_desc_set_pq_src_addr(g, i++, dst[1], 1);
-               else if (dmaf_continue(flags)) {
-                       iop_desc_set_pq_src_addr(g, i++, dst[0], 0);
-                       iop_desc_set_pq_src_addr(g, i++, dst[1], 1);
-                       iop_desc_set_pq_src_addr(g, i++, dst[1], 0);
-               }
-               iop_desc_init_pq(g, i, flags);
-       }
-       spin_unlock_bh(&iop_chan->lock);
-
-       return sw_desc ? &sw_desc->async_tx : NULL;
-}
-
-static struct dma_async_tx_descriptor *
-iop_adma_prep_dma_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,
-                        unsigned int src_cnt, const unsigned char *scf,
-                        size_t len, enum sum_check_flags *pqres,
-                        unsigned long flags)
-{
-       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-       struct iop_adma_desc_slot *sw_desc, *g;
-       int slot_cnt, slots_per_op;
-
-       if (unlikely(!len))
-               return NULL;
-       BUG_ON(len > IOP_ADMA_XOR_MAX_BYTE_COUNT);
-
-       dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %zu\n",
-               __func__, src_cnt, len);
-
-       spin_lock_bh(&iop_chan->lock);
-       slot_cnt = iop_chan_pq_zero_sum_slot_count(len, src_cnt + 2, &slots_per_op);
-       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-       if (sw_desc) {
-               /* for validate operations p and q are tagged onto the
-                * end of the source list
-                */
-               int pq_idx = src_cnt;
-
-               g = sw_desc->group_head;
-               iop_desc_init_pq_zero_sum(g, src_cnt+2, flags);
-               iop_desc_set_pq_zero_sum_byte_count(g, len);
-               g->pq_check_result = pqres;
-               pr_debug("\t%s: g->pq_check_result: %p\n",
-                       __func__, g->pq_check_result);
-               sw_desc->async_tx.flags = flags;
-               while (src_cnt--)
-                       iop_desc_set_pq_zero_sum_src_addr(g, src_cnt,
-                                                         src[src_cnt],
-                                                         scf[src_cnt]);
-               iop_desc_set_pq_zero_sum_addr(g, pq_idx, src);
-       }
-       spin_unlock_bh(&iop_chan->lock);
-
-       return sw_desc ? &sw_desc->async_tx : NULL;
-}
-
-static void iop_adma_free_chan_resources(struct dma_chan *chan)
-{
-       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-       struct iop_adma_desc_slot *iter, *_iter;
-       int in_use_descs = 0;
-
-       iop_adma_slot_cleanup(iop_chan);
-
-       spin_lock_bh(&iop_chan->lock);
-       list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
-                                       chain_node) {
-               in_use_descs++;
-               list_del(&iter->chain_node);
-       }
-       list_for_each_entry_safe_reverse(
-               iter, _iter, &iop_chan->all_slots, slot_node) {
-               list_del(&iter->slot_node);
-               kfree(iter);
-               iop_chan->slots_allocated--;
-       }
-       iop_chan->last_used = NULL;
-
-       dev_dbg(iop_chan->device->common.dev, "%s slots_allocated %d\n",
-               __func__, iop_chan->slots_allocated);
-       spin_unlock_bh(&iop_chan->lock);
-
-       /* one is ok since we left it on there on purpose */
-       if (in_use_descs > 1)
-               printk(KERN_ERR "IOP: Freeing %d in use descriptors!\n",
-                       in_use_descs - 1);
-}
-
-/**
- * iop_adma_status - poll the status of an ADMA transaction
- * @chan: ADMA channel handle
- * @cookie: ADMA transaction identifier
- * @txstate: a holder for the current state of the channel or NULL
- */
-static enum dma_status iop_adma_status(struct dma_chan *chan,
-                                       dma_cookie_t cookie,
-                                       struct dma_tx_state *txstate)
-{
-       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-       int ret;
-
-       ret = dma_cookie_status(chan, cookie, txstate);
-       if (ret == DMA_COMPLETE)
-               return ret;
-
-       iop_adma_slot_cleanup(iop_chan);
-
-       return dma_cookie_status(chan, cookie, txstate);
-}
-
-static irqreturn_t iop_adma_eot_handler(int irq, void *data)
-{
-       struct iop_adma_chan *chan = data;
-
-       dev_dbg(chan->device->common.dev, "%s\n", __func__);
-
-       tasklet_schedule(&chan->irq_tasklet);
-
-       iop_adma_device_clear_eot_status(chan);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t iop_adma_eoc_handler(int irq, void *data)
-{
-       struct iop_adma_chan *chan = data;
-
-       dev_dbg(chan->device->common.dev, "%s\n", __func__);
-
-       tasklet_schedule(&chan->irq_tasklet);
-
-       iop_adma_device_clear_eoc_status(chan);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t iop_adma_err_handler(int irq, void *data)
-{
-       struct iop_adma_chan *chan = data;
-       unsigned long status = iop_chan_get_status(chan);
-
-       dev_err(chan->device->common.dev,
-               "error ( %s%s%s%s%s%s%s)\n",
-               iop_is_err_int_parity(status, chan) ? "int_parity " : "",
-               iop_is_err_mcu_abort(status, chan) ? "mcu_abort " : "",
-               iop_is_err_int_tabort(status, chan) ? "int_tabort " : "",
-               iop_is_err_int_mabort(status, chan) ? "int_mabort " : "",
-               iop_is_err_pci_tabort(status, chan) ? "pci_tabort " : "",
-               iop_is_err_pci_mabort(status, chan) ? "pci_mabort " : "",
-               iop_is_err_split_tx(status, chan) ? "split_tx " : "");
-
-       iop_adma_device_clear_err_status(chan);
-
-       BUG();
-
-       return IRQ_HANDLED;
-}
-
-static void iop_adma_issue_pending(struct dma_chan *chan)
-{
-       struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
-
-       if (iop_chan->pending) {
-               iop_chan->pending = 0;
-               iop_chan_append(iop_chan);
-       }
-}
-
-/*
- * Perform a transaction to verify the HW works.
- */
-#define IOP_ADMA_TEST_SIZE 2000
-
-static int iop_adma_memcpy_self_test(struct iop_adma_device *device)
-{
-       int i;
-       void *src, *dest;
-       dma_addr_t src_dma, dest_dma;
-       struct dma_chan *dma_chan;
-       dma_cookie_t cookie;
-       struct dma_async_tx_descriptor *tx;
-       int err = 0;
-       struct iop_adma_chan *iop_chan;
-
-       dev_dbg(device->common.dev, "%s\n", __func__);
-
-       src = kmalloc(IOP_ADMA_TEST_SIZE, GFP_KERNEL);
-       if (!src)
-               return -ENOMEM;
-       dest = kzalloc(IOP_ADMA_TEST_SIZE, GFP_KERNEL);
-       if (!dest) {
-               kfree(src);
-               return -ENOMEM;
-       }
-
-       /* Fill in src buffer */
-       for (i = 0; i < IOP_ADMA_TEST_SIZE; i++)
-               ((u8 *) src)[i] = (u8)i;
-
-       /* Start copy, using first DMA channel */
-       dma_chan = container_of(device->common.channels.next,
-                               struct dma_chan,
-                               device_node);
-       if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
-               err = -ENODEV;
-               goto out;
-       }
-
-       dest_dma = dma_map_single(dma_chan->device->dev, dest,
-                               IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
-       src_dma = dma_map_single(dma_chan->device->dev, src,
-                               IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE);
-       tx = iop_adma_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
-                                     IOP_ADMA_TEST_SIZE,
-                                     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
-       cookie = iop_adma_tx_submit(tx);
-       iop_adma_issue_pending(dma_chan);
-       msleep(1);
-
-       if (iop_adma_status(dma_chan, cookie, NULL) !=
-                       DMA_COMPLETE) {
-               dev_err(dma_chan->device->dev,
-                       "Self-test copy timed out, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-       iop_chan = to_iop_adma_chan(dma_chan);
-       dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
-               IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
-       if (memcmp(src, dest, IOP_ADMA_TEST_SIZE)) {
-               dev_err(dma_chan->device->dev,
-                       "Self-test copy failed compare, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-free_resources:
-       iop_adma_free_chan_resources(dma_chan);
-out:
-       kfree(src);
-       kfree(dest);
-       return err;
-}
-
-#define IOP_ADMA_NUM_SRC_TEST 4 /* must be <= 15 */
-static int
-iop_adma_xor_val_self_test(struct iop_adma_device *device)
-{
-       int i, src_idx;
-       struct page *dest;
-       struct page *xor_srcs[IOP_ADMA_NUM_SRC_TEST];
-       struct page *zero_sum_srcs[IOP_ADMA_NUM_SRC_TEST + 1];
-       dma_addr_t dma_srcs[IOP_ADMA_NUM_SRC_TEST + 1];
-       dma_addr_t dest_dma;
-       struct dma_async_tx_descriptor *tx;
-       struct dma_chan *dma_chan;
-       dma_cookie_t cookie;
-       u8 cmp_byte = 0;
-       u32 cmp_word;
-       u32 zero_sum_result;
-       int err = 0;
-       struct iop_adma_chan *iop_chan;
-
-       dev_dbg(device->common.dev, "%s\n", __func__);
-
-       for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
-               xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
-               if (!xor_srcs[src_idx]) {
-                       while (src_idx--)
-                               __free_page(xor_srcs[src_idx]);
-                       return -ENOMEM;
-               }
-       }
-
-       dest = alloc_page(GFP_KERNEL);
-       if (!dest) {
-               while (src_idx--)
-                       __free_page(xor_srcs[src_idx]);
-               return -ENOMEM;
-       }
-
-       /* Fill in src buffers */
-       for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
-               u8 *ptr = page_address(xor_srcs[src_idx]);
-               for (i = 0; i < PAGE_SIZE; i++)
-                       ptr[i] = (1 << src_idx);
-       }
-
-       for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++)
-               cmp_byte ^= (u8) (1 << src_idx);
-
-       cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
-                       (cmp_byte << 8) | cmp_byte;
-
-       memset(page_address(dest), 0, PAGE_SIZE);
-
-       dma_chan = container_of(device->common.channels.next,
-                               struct dma_chan,
-                               device_node);
-       if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
-               err = -ENODEV;
-               goto out;
-       }
-
-       /* test xor */
-       dest_dma = dma_map_page(dma_chan->device->dev, dest, 0,
-                               PAGE_SIZE, DMA_FROM_DEVICE);
-       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++)
-               dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
-                                          0, PAGE_SIZE, DMA_TO_DEVICE);
-       tx = iop_adma_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
-                                  IOP_ADMA_NUM_SRC_TEST, PAGE_SIZE,
-                                  DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
-       cookie = iop_adma_tx_submit(tx);
-       iop_adma_issue_pending(dma_chan);
-       msleep(8);
-
-       if (iop_adma_status(dma_chan, cookie, NULL) !=
-               DMA_COMPLETE) {
-               dev_err(dma_chan->device->dev,
-                       "Self-test xor timed out, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-       iop_chan = to_iop_adma_chan(dma_chan);
-       dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
-               PAGE_SIZE, DMA_FROM_DEVICE);
-       for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
-               u32 *ptr = page_address(dest);
-               if (ptr[i] != cmp_word) {
-                       dev_err(dma_chan->device->dev,
-                               "Self-test xor failed compare, disabling\n");
-                       err = -ENODEV;
-                       goto free_resources;
-               }
-       }
-       dma_sync_single_for_device(&iop_chan->device->pdev->dev, dest_dma,
-               PAGE_SIZE, DMA_TO_DEVICE);
-
-       /* skip zero sum if the capability is not present */
-       if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask))
-               goto free_resources;
-
-       /* zero sum the sources with the destintation page */
-       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++)
-               zero_sum_srcs[i] = xor_srcs[i];
-       zero_sum_srcs[i] = dest;
-
-       zero_sum_result = 1;
-
-       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++)
-               dma_srcs[i] = dma_map_page(dma_chan->device->dev,
-                                          zero_sum_srcs[i], 0, PAGE_SIZE,
-                                          DMA_TO_DEVICE);
-       tx = iop_adma_prep_dma_xor_val(dma_chan, dma_srcs,
-                                      IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE,
-                                      &zero_sum_result,
-                                      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
-       cookie = iop_adma_tx_submit(tx);
-       iop_adma_issue_pending(dma_chan);
-       msleep(8);
-
-       if (iop_adma_status(dma_chan, cookie, NULL) != DMA_COMPLETE) {
-               dev_err(dma_chan->device->dev,
-                       "Self-test zero sum timed out, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-       if (zero_sum_result != 0) {
-               dev_err(dma_chan->device->dev,
-                       "Self-test zero sum failed compare, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-       /* test for non-zero parity sum */
-       zero_sum_result = 0;
-       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++)
-               dma_srcs[i] = dma_map_page(dma_chan->device->dev,
-                                          zero_sum_srcs[i], 0, PAGE_SIZE,
-                                          DMA_TO_DEVICE);
-       tx = iop_adma_prep_dma_xor_val(dma_chan, dma_srcs,
-                                      IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE,
-                                      &zero_sum_result,
-                                      DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
-       cookie = iop_adma_tx_submit(tx);
-       iop_adma_issue_pending(dma_chan);
-       msleep(8);
-
-       if (iop_adma_status(dma_chan, cookie, NULL) != DMA_COMPLETE) {
-               dev_err(dma_chan->device->dev,
-                       "Self-test non-zero sum timed out, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-       if (zero_sum_result != 1) {
-               dev_err(dma_chan->device->dev,
-                       "Self-test non-zero sum failed compare, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-free_resources:
-       iop_adma_free_chan_resources(dma_chan);
-out:
-       src_idx = IOP_ADMA_NUM_SRC_TEST;
-       while (src_idx--)
-               __free_page(xor_srcs[src_idx]);
-       __free_page(dest);
-       return err;
-}
-
-#ifdef CONFIG_RAID6_PQ
-static int
-iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device)
-{
-       /* combined sources, software pq results, and extra hw pq results */
-       struct page *pq[IOP_ADMA_NUM_SRC_TEST+2+2];
-       /* ptr to the extra hw pq buffers defined above */
-       struct page **pq_hw = &pq[IOP_ADMA_NUM_SRC_TEST+2];
-       /* address conversion buffers (dma_map / page_address) */
-       void *pq_sw[IOP_ADMA_NUM_SRC_TEST+2];
-       dma_addr_t pq_src[IOP_ADMA_NUM_SRC_TEST+2];
-       dma_addr_t *pq_dest = &pq_src[IOP_ADMA_NUM_SRC_TEST];
-
-       int i;
-       struct dma_async_tx_descriptor *tx;
-       struct dma_chan *dma_chan;
-       dma_cookie_t cookie;
-       u32 zero_sum_result;
-       int err = 0;
-       struct device *dev;
-
-       dev_dbg(device->common.dev, "%s\n", __func__);
-
-       for (i = 0; i < ARRAY_SIZE(pq); i++) {
-               pq[i] = alloc_page(GFP_KERNEL);
-               if (!pq[i]) {
-                       while (i--)
-                               __free_page(pq[i]);
-                       return -ENOMEM;
-               }
-       }
-
-       /* Fill in src buffers */
-       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) {
-               pq_sw[i] = page_address(pq[i]);
-               memset(pq_sw[i], 0x11111111 * (1<<i), PAGE_SIZE);
-       }
-       pq_sw[i] = page_address(pq[i]);
-       pq_sw[i+1] = page_address(pq[i+1]);
-
-       dma_chan = container_of(device->common.channels.next,
-                               struct dma_chan,
-                               device_node);
-       if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
-               err = -ENODEV;
-               goto out;
-       }
-
-       dev = dma_chan->device->dev;
-
-       /* initialize the dests */
-       memset(page_address(pq_hw[0]), 0 , PAGE_SIZE);
-       memset(page_address(pq_hw[1]), 0 , PAGE_SIZE);
-
-       /* test pq */
-       pq_dest[0] = dma_map_page(dev, pq_hw[0], 0, PAGE_SIZE, DMA_FROM_DEVICE);
-       pq_dest[1] = dma_map_page(dev, pq_hw[1], 0, PAGE_SIZE, DMA_FROM_DEVICE);
-       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++)
-               pq_src[i] = dma_map_page(dev, pq[i], 0, PAGE_SIZE,
-                                        DMA_TO_DEVICE);
-
-       tx = iop_adma_prep_dma_pq(dma_chan, pq_dest, pq_src,
-                                 IOP_ADMA_NUM_SRC_TEST, (u8 *)raid6_gfexp,
-                                 PAGE_SIZE,
-                                 DMA_PREP_INTERRUPT |
-                                 DMA_CTRL_ACK);
-
-       cookie = iop_adma_tx_submit(tx);
-       iop_adma_issue_pending(dma_chan);
-       msleep(8);
-
-       if (iop_adma_status(dma_chan, cookie, NULL) !=
-               DMA_COMPLETE) {
-               dev_err(dev, "Self-test pq timed out, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-       raid6_call.gen_syndrome(IOP_ADMA_NUM_SRC_TEST+2, PAGE_SIZE, pq_sw);
-
-       if (memcmp(pq_sw[IOP_ADMA_NUM_SRC_TEST],
-                  page_address(pq_hw[0]), PAGE_SIZE) != 0) {
-               dev_err(dev, "Self-test p failed compare, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-       if (memcmp(pq_sw[IOP_ADMA_NUM_SRC_TEST+1],
-                  page_address(pq_hw[1]), PAGE_SIZE) != 0) {
-               dev_err(dev, "Self-test q failed compare, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-       /* test correct zero sum using the software generated pq values */
-       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 2; i++)
-               pq_src[i] = dma_map_page(dev, pq[i], 0, PAGE_SIZE,
-                                        DMA_TO_DEVICE);
-
-       zero_sum_result = ~0;
-       tx = iop_adma_prep_dma_pq_val(dma_chan, &pq_src[IOP_ADMA_NUM_SRC_TEST],
-                                     pq_src, IOP_ADMA_NUM_SRC_TEST,
-                                     raid6_gfexp, PAGE_SIZE, &zero_sum_result,
-                                     DMA_PREP_INTERRUPT|DMA_CTRL_ACK);
-
-       cookie = iop_adma_tx_submit(tx);
-       iop_adma_issue_pending(dma_chan);
-       msleep(8);
-
-       if (iop_adma_status(dma_chan, cookie, NULL) !=
-               DMA_COMPLETE) {
-               dev_err(dev, "Self-test pq-zero-sum timed out, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-       if (zero_sum_result != 0) {
-               dev_err(dev, "Self-test pq-zero-sum failed to validate: %x\n",
-                       zero_sum_result);
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-       /* test incorrect zero sum */
-       i = IOP_ADMA_NUM_SRC_TEST;
-       memset(pq_sw[i] + 100, 0, 100);
-       memset(pq_sw[i+1] + 200, 0, 200);
-       for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 2; i++)
-               pq_src[i] = dma_map_page(dev, pq[i], 0, PAGE_SIZE,
-                                        DMA_TO_DEVICE);
-
-       zero_sum_result = 0;
-       tx = iop_adma_prep_dma_pq_val(dma_chan, &pq_src[IOP_ADMA_NUM_SRC_TEST],
-                                     pq_src, IOP_ADMA_NUM_SRC_TEST,
-                                     raid6_gfexp, PAGE_SIZE, &zero_sum_result,
-                                     DMA_PREP_INTERRUPT|DMA_CTRL_ACK);
-
-       cookie = iop_adma_tx_submit(tx);
-       iop_adma_issue_pending(dma_chan);
-       msleep(8);
-
-       if (iop_adma_status(dma_chan, cookie, NULL) !=
-               DMA_COMPLETE) {
-               dev_err(dev, "Self-test !pq-zero-sum timed out, disabling\n");
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-       if (zero_sum_result != (SUM_CHECK_P_RESULT | SUM_CHECK_Q_RESULT)) {
-               dev_err(dev, "Self-test !pq-zero-sum failed to validate: %x\n",
-                       zero_sum_result);
-               err = -ENODEV;
-               goto free_resources;
-       }
-
-free_resources:
-       iop_adma_free_chan_resources(dma_chan);
-out:
-       i = ARRAY_SIZE(pq);
-       while (i--)
-               __free_page(pq[i]);
-       return err;
-}
-#endif
-
-static int iop_adma_remove(struct platform_device *dev)
-{
-       struct iop_adma_device *device = platform_get_drvdata(dev);
-       struct dma_chan *chan, *_chan;
-       struct iop_adma_chan *iop_chan;
-       struct iop_adma_platform_data *plat_data = dev_get_platdata(&dev->dev);
-
-       dma_async_device_unregister(&device->common);
-
-       dma_free_coherent(&dev->dev, plat_data->pool_size,
-                       device->dma_desc_pool_virt, device->dma_desc_pool);
-
-       list_for_each_entry_safe(chan, _chan, &device->common.channels,
-                               device_node) {
-               iop_chan = to_iop_adma_chan(chan);
-               list_del(&chan->device_node);
-               kfree(iop_chan);
-       }
-       kfree(device);
-
-       return 0;
-}
-
-static int iop_adma_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       int ret = 0, i;
-       struct iop_adma_device *adev;
-       struct iop_adma_chan *iop_chan;
-       struct dma_device *dma_dev;
-       struct iop_adma_platform_data *plat_data = dev_get_platdata(&pdev->dev);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENODEV;
-
-       if (!devm_request_mem_region(&pdev->dev, res->start,
-                               resource_size(res), pdev->name))
-               return -EBUSY;
-
-       adev = kzalloc(sizeof(*adev), GFP_KERNEL);
-       if (!adev)
-               return -ENOMEM;
-       dma_dev = &adev->common;
-
-       /* allocate coherent memory for hardware descriptors
-        * note: writecombine gives slightly better performance, but
-        * requires that we explicitly flush the writes
-        */
-       adev->dma_desc_pool_virt = dma_alloc_wc(&pdev->dev,
-                                               plat_data->pool_size,
-                                               &adev->dma_desc_pool,
-                                               GFP_KERNEL);
-       if (!adev->dma_desc_pool_virt) {
-               ret = -ENOMEM;
-               goto err_free_adev;
-       }
-
-       dev_dbg(&pdev->dev, "%s: allocated descriptor pool virt %p phys %pad\n",
-               __func__, adev->dma_desc_pool_virt, &adev->dma_desc_pool);
-
-       adev->id = plat_data->hw_id;
-
-       /* discover transaction capabilites from the platform data */
-       dma_dev->cap_mask = plat_data->cap_mask;
-
-       adev->pdev = pdev;
-       platform_set_drvdata(pdev, adev);
-
-       INIT_LIST_HEAD(&dma_dev->channels);
-
-       /* set base routines */
-       dma_dev->device_alloc_chan_resources = iop_adma_alloc_chan_resources;
-       dma_dev->device_free_chan_resources = iop_adma_free_chan_resources;
-       dma_dev->device_tx_status = iop_adma_status;
-       dma_dev->device_issue_pending = iop_adma_issue_pending;
-       dma_dev->dev = &pdev->dev;
-
-       /* set prep routines based on capability */
-       if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask))
-               dma_dev->device_prep_dma_memcpy = iop_adma_prep_dma_memcpy;
-       if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
-               dma_dev->max_xor = iop_adma_get_max_xor();
-               dma_dev->device_prep_dma_xor = iop_adma_prep_dma_xor;
-       }
-       if (dma_has_cap(DMA_XOR_VAL, dma_dev->cap_mask))
-               dma_dev->device_prep_dma_xor_val =
-                       iop_adma_prep_dma_xor_val;
-       if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {
-               dma_set_maxpq(dma_dev, iop_adma_get_max_pq(), 0);
-               dma_dev->device_prep_dma_pq = iop_adma_prep_dma_pq;
-       }
-       if (dma_has_cap(DMA_PQ_VAL, dma_dev->cap_mask))
-               dma_dev->device_prep_dma_pq_val =
-                       iop_adma_prep_dma_pq_val;
-       if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask))
-               dma_dev->device_prep_dma_interrupt =
-                       iop_adma_prep_dma_interrupt;
-
-       iop_chan = kzalloc(sizeof(*iop_chan), GFP_KERNEL);
-       if (!iop_chan) {
-               ret = -ENOMEM;
-               goto err_free_dma;
-       }
-       iop_chan->device = adev;
-
-       iop_chan->mmr_base = devm_ioremap(&pdev->dev, res->start,
-                                       resource_size(res));
-       if (!iop_chan->mmr_base) {
-               ret = -ENOMEM;
-               goto err_free_iop_chan;
-       }
-       tasklet_setup(&iop_chan->irq_tasklet, iop_adma_tasklet);
-
-       /* clear errors before enabling interrupts */
-       iop_adma_device_clear_err_status(iop_chan);
-
-       for (i = 0; i < 3; i++) {
-               static const irq_handler_t handler[] = {
-                       iop_adma_eot_handler,
-                       iop_adma_eoc_handler,
-                       iop_adma_err_handler
-               };
-               int irq = platform_get_irq(pdev, i);
-               if (irq < 0) {
-                       ret = -ENXIO;
-                       goto err_free_iop_chan;
-               } else {
-                       ret = devm_request_irq(&pdev->dev, irq,
-                                       handler[i], 0, pdev->name, iop_chan);
-                       if (ret)
-                               goto err_free_iop_chan;
-               }
-       }
-
-       spin_lock_init(&iop_chan->lock);
-       INIT_LIST_HEAD(&iop_chan->chain);
-       INIT_LIST_HEAD(&iop_chan->all_slots);
-       iop_chan->common.device = dma_dev;
-       dma_cookie_init(&iop_chan->common);
-       list_add_tail(&iop_chan->common.device_node, &dma_dev->channels);
-
-       if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
-               ret = iop_adma_memcpy_self_test(adev);
-               dev_dbg(&pdev->dev, "memcpy self test returned %d\n", ret);
-               if (ret)
-                       goto err_free_iop_chan;
-       }
-
-       if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
-               ret = iop_adma_xor_val_self_test(adev);
-               dev_dbg(&pdev->dev, "xor self test returned %d\n", ret);
-               if (ret)
-                       goto err_free_iop_chan;
-       }
-
-       if (dma_has_cap(DMA_PQ, dma_dev->cap_mask) &&
-           dma_has_cap(DMA_PQ_VAL, dma_dev->cap_mask)) {
-               #ifdef CONFIG_RAID6_PQ
-               ret = iop_adma_pq_zero_sum_self_test(adev);
-               dev_dbg(&pdev->dev, "pq self test returned %d\n", ret);
-               #else
-               /* can not test raid6, so do not publish capability */
-               dma_cap_clear(DMA_PQ, dma_dev->cap_mask);
-               dma_cap_clear(DMA_PQ_VAL, dma_dev->cap_mask);
-               ret = 0;
-               #endif
-               if (ret)
-                       goto err_free_iop_chan;
-       }
-
-       dev_info(&pdev->dev, "Intel(R) IOP: ( %s%s%s%s%s%s)\n",
-                dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "pq " : "",
-                dma_has_cap(DMA_PQ_VAL, dma_dev->cap_mask) ? "pq_val " : "",
-                dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
-                dma_has_cap(DMA_XOR_VAL, dma_dev->cap_mask) ? "xor_val " : "",
-                dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
-                dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
-
-       dma_async_device_register(dma_dev);
-       goto out;
-
- err_free_iop_chan:
-       kfree(iop_chan);
- err_free_dma:
-       dma_free_coherent(&adev->pdev->dev, plat_data->pool_size,
-                       adev->dma_desc_pool_virt, adev->dma_desc_pool);
- err_free_adev:
-       kfree(adev);
- out:
-       return ret;
-}
-
-static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
-{
-       struct iop_adma_desc_slot *sw_desc, *grp_start;
-       dma_cookie_t cookie;
-       int slot_cnt, slots_per_op;
-
-       dev_dbg(iop_chan->device->common.dev, "%s\n", __func__);
-
-       spin_lock_bh(&iop_chan->lock);
-       slot_cnt = iop_chan_memcpy_slot_count(0, &slots_per_op);
-       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-       if (sw_desc) {
-               grp_start = sw_desc->group_head;
-
-               list_splice_init(&sw_desc->tx_list, &iop_chan->chain);
-               async_tx_ack(&sw_desc->async_tx);
-               iop_desc_init_memcpy(grp_start, 0);
-               iop_desc_set_byte_count(grp_start, iop_chan, 0);
-               iop_desc_set_dest_addr(grp_start, iop_chan, 0);
-               iop_desc_set_memcpy_src_addr(grp_start, 0);
-
-               cookie = dma_cookie_assign(&sw_desc->async_tx);
-
-               /* initialize the completed cookie to be less than
-                * the most recently used cookie
-                */
-               iop_chan->common.completed_cookie = cookie - 1;
-
-               /* channel should not be busy */
-               BUG_ON(iop_chan_is_busy(iop_chan));
-
-               /* clear any prior error-status bits */
-               iop_adma_device_clear_err_status(iop_chan);
-
-               /* disable operation */
-               iop_chan_disable(iop_chan);
-
-               /* set the descriptor address */
-               iop_chan_set_next_descriptor(iop_chan, sw_desc->async_tx.phys);
-
-               /* 1/ don't add pre-chained descriptors
-                * 2/ dummy read to flush next_desc write
-                */
-               BUG_ON(iop_desc_get_next_desc(sw_desc));
-
-               /* run the descriptor */
-               iop_chan_enable(iop_chan);
-       } else
-               dev_err(iop_chan->device->common.dev,
-                       "failed to allocate null descriptor\n");
-       spin_unlock_bh(&iop_chan->lock);
-}
-
-static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
-{
-       struct iop_adma_desc_slot *sw_desc, *grp_start;
-       dma_cookie_t cookie;
-       int slot_cnt, slots_per_op;
-
-       dev_dbg(iop_chan->device->common.dev, "%s\n", __func__);
-
-       spin_lock_bh(&iop_chan->lock);
-       slot_cnt = iop_chan_xor_slot_count(0, 2, &slots_per_op);
-       sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
-       if (sw_desc) {
-               grp_start = sw_desc->group_head;
-               list_splice_init(&sw_desc->tx_list, &iop_chan->chain);
-               async_tx_ack(&sw_desc->async_tx);
-               iop_desc_init_null_xor(grp_start, 2, 0);
-               iop_desc_set_byte_count(grp_start, iop_chan, 0);
-               iop_desc_set_dest_addr(grp_start, iop_chan, 0);
-               iop_desc_set_xor_src_addr(grp_start, 0, 0);
-               iop_desc_set_xor_src_addr(grp_start, 1, 0);
-
-               cookie = dma_cookie_assign(&sw_desc->async_tx);
-
-               /* initialize the completed cookie to be less than
-                * the most recently used cookie
-                */
-               iop_chan->common.completed_cookie = cookie - 1;
-
-               /* channel should not be busy */
-               BUG_ON(iop_chan_is_busy(iop_chan));
-
-               /* clear any prior error-status bits */
-               iop_adma_device_clear_err_status(iop_chan);
-
-               /* disable operation */
-               iop_chan_disable(iop_chan);
-
-               /* set the descriptor address */
-               iop_chan_set_next_descriptor(iop_chan, sw_desc->async_tx.phys);
-
-               /* 1/ don't add pre-chained descriptors
-                * 2/ dummy read to flush next_desc write
-                */
-               BUG_ON(iop_desc_get_next_desc(sw_desc));
-
-               /* run the descriptor */
-               iop_chan_enable(iop_chan);
-       } else
-               dev_err(iop_chan->device->common.dev,
-                       "failed to allocate null descriptor\n");
-       spin_unlock_bh(&iop_chan->lock);
-}
-
-static struct platform_driver iop_adma_driver = {
-       .probe          = iop_adma_probe,
-       .remove         = iop_adma_remove,
-       .driver         = {
-               .name   = "iop-adma",
-       },
-};
-
-module_platform_driver(iop_adma_driver);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("IOP ADMA Engine Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:iop-adma");
diff --git a/drivers/dma/iop-adma.h b/drivers/dma/iop-adma.h
deleted file mode 100644 (file)
index d44eabb..0000000
+++ /dev/null
@@ -1,914 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright Â© 2006, Intel Corporation.
- */
-#ifndef _ADMA_H
-#define _ADMA_H
-#include <linux/types.h>
-#include <linux/io.h>
-#include <linux/platform_data/dma-iop32x.h>
-
-/* Memory copy units */
-#define DMA_CCR(chan)          (chan->mmr_base + 0x0)
-#define DMA_CSR(chan)          (chan->mmr_base + 0x4)
-#define DMA_DAR(chan)          (chan->mmr_base + 0xc)
-#define DMA_NDAR(chan)         (chan->mmr_base + 0x10)
-#define DMA_PADR(chan)         (chan->mmr_base + 0x14)
-#define DMA_PUADR(chan)        (chan->mmr_base + 0x18)
-#define DMA_LADR(chan)         (chan->mmr_base + 0x1c)
-#define DMA_BCR(chan)          (chan->mmr_base + 0x20)
-#define DMA_DCR(chan)          (chan->mmr_base + 0x24)
-
-/* Application accelerator unit  */
-#define AAU_ACR(chan)          (chan->mmr_base + 0x0)
-#define AAU_ASR(chan)          (chan->mmr_base + 0x4)
-#define AAU_ADAR(chan)         (chan->mmr_base + 0x8)
-#define AAU_ANDAR(chan)        (chan->mmr_base + 0xc)
-#define AAU_SAR(src, chan)     (chan->mmr_base + (0x10 + ((src) << 2)))
-#define AAU_DAR(chan)          (chan->mmr_base + 0x20)
-#define AAU_ABCR(chan)         (chan->mmr_base + 0x24)
-#define AAU_ADCR(chan)         (chan->mmr_base + 0x28)
-#define AAU_SAR_EDCR(src_edc)  (chan->mmr_base + (0x02c + ((src_edc-4) << 2)))
-#define AAU_EDCR0_IDX  8
-#define AAU_EDCR1_IDX  17
-#define AAU_EDCR2_IDX  26
-
-struct iop3xx_aau_desc_ctrl {
-       unsigned int int_en:1;
-       unsigned int blk1_cmd_ctrl:3;
-       unsigned int blk2_cmd_ctrl:3;
-       unsigned int blk3_cmd_ctrl:3;
-       unsigned int blk4_cmd_ctrl:3;
-       unsigned int blk5_cmd_ctrl:3;
-       unsigned int blk6_cmd_ctrl:3;
-       unsigned int blk7_cmd_ctrl:3;
-       unsigned int blk8_cmd_ctrl:3;
-       unsigned int blk_ctrl:2;
-       unsigned int dual_xor_en:1;
-       unsigned int tx_complete:1;
-       unsigned int zero_result_err:1;
-       unsigned int zero_result_en:1;
-       unsigned int dest_write_en:1;
-};
-
-struct iop3xx_aau_e_desc_ctrl {
-       unsigned int reserved:1;
-       unsigned int blk1_cmd_ctrl:3;
-       unsigned int blk2_cmd_ctrl:3;
-       unsigned int blk3_cmd_ctrl:3;
-       unsigned int blk4_cmd_ctrl:3;
-       unsigned int blk5_cmd_ctrl:3;
-       unsigned int blk6_cmd_ctrl:3;
-       unsigned int blk7_cmd_ctrl:3;
-       unsigned int blk8_cmd_ctrl:3;
-       unsigned int reserved2:7;
-};
-
-struct iop3xx_dma_desc_ctrl {
-       unsigned int pci_transaction:4;
-       unsigned int int_en:1;
-       unsigned int dac_cycle_en:1;
-       unsigned int mem_to_mem_en:1;
-       unsigned int crc_data_tx_en:1;
-       unsigned int crc_gen_en:1;
-       unsigned int crc_seed_dis:1;
-       unsigned int reserved:21;
-       unsigned int crc_tx_complete:1;
-};
-
-struct iop3xx_desc_dma {
-       u32 next_desc;
-       union {
-               u32 pci_src_addr;
-               u32 pci_dest_addr;
-               u32 src_addr;
-       };
-       union {
-               u32 upper_pci_src_addr;
-               u32 upper_pci_dest_addr;
-       };
-       union {
-               u32 local_pci_src_addr;
-               u32 local_pci_dest_addr;
-               u32 dest_addr;
-       };
-       u32 byte_count;
-       union {
-               u32 desc_ctrl;
-               struct iop3xx_dma_desc_ctrl desc_ctrl_field;
-       };
-       u32 crc_addr;
-};
-
-struct iop3xx_desc_aau {
-       u32 next_desc;
-       u32 src[4];
-       u32 dest_addr;
-       u32 byte_count;
-       union {
-               u32 desc_ctrl;
-               struct iop3xx_aau_desc_ctrl desc_ctrl_field;
-       };
-       union {
-               u32 src_addr;
-               u32 e_desc_ctrl;
-               struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
-       } src_edc[31];
-};
-
-struct iop3xx_aau_gfmr {
-       unsigned int gfmr1:8;
-       unsigned int gfmr2:8;
-       unsigned int gfmr3:8;
-       unsigned int gfmr4:8;
-};
-
-struct iop3xx_desc_pq_xor {
-       u32 next_desc;
-       u32 src[3];
-       union {
-               u32 data_mult1;
-               struct iop3xx_aau_gfmr data_mult1_field;
-       };
-       u32 dest_addr;
-       u32 byte_count;
-       union {
-               u32 desc_ctrl;
-               struct iop3xx_aau_desc_ctrl desc_ctrl_field;
-       };
-       union {
-               u32 src_addr;
-               u32 e_desc_ctrl;
-               struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
-               u32 data_multiplier;
-               struct iop3xx_aau_gfmr data_mult_field;
-               u32 reserved;
-       } src_edc_gfmr[19];
-};
-
-struct iop3xx_desc_dual_xor {
-       u32 next_desc;
-       u32 src0_addr;
-       u32 src1_addr;
-       u32 h_src_addr;
-       u32 d_src_addr;
-       u32 h_dest_addr;
-       u32 byte_count;
-       union {
-               u32 desc_ctrl;
-               struct iop3xx_aau_desc_ctrl desc_ctrl_field;
-       };
-       u32 d_dest_addr;
-};
-
-union iop3xx_desc {
-       struct iop3xx_desc_aau *aau;
-       struct iop3xx_desc_dma *dma;
-       struct iop3xx_desc_pq_xor *pq_xor;
-       struct iop3xx_desc_dual_xor *dual_xor;
-       void *ptr;
-};
-
-/* No support for p+q operations */
-static inline int
-iop_chan_pq_slot_count(size_t len, int src_cnt, int *slots_per_op)
-{
-       BUG();
-       return 0;
-}
-
-static inline void
-iop_desc_init_pq(struct iop_adma_desc_slot *desc, int src_cnt,
-                 unsigned long flags)
-{
-       BUG();
-}
-
-static inline void
-iop_desc_set_pq_addr(struct iop_adma_desc_slot *desc, dma_addr_t *addr)
-{
-       BUG();
-}
-
-static inline void
-iop_desc_set_pq_src_addr(struct iop_adma_desc_slot *desc, int src_idx,
-                        dma_addr_t addr, unsigned char coef)
-{
-       BUG();
-}
-
-static inline int
-iop_chan_pq_zero_sum_slot_count(size_t len, int src_cnt, int *slots_per_op)
-{
-       BUG();
-       return 0;
-}
-
-static inline void
-iop_desc_init_pq_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt,
-                         unsigned long flags)
-{
-       BUG();
-}
-
-static inline void
-iop_desc_set_pq_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
-{
-       BUG();
-}
-
-#define iop_desc_set_pq_zero_sum_src_addr iop_desc_set_pq_src_addr
-
-static inline void
-iop_desc_set_pq_zero_sum_addr(struct iop_adma_desc_slot *desc, int pq_idx,
-                             dma_addr_t *src)
-{
-       BUG();
-}
-
-static inline int iop_adma_get_max_xor(void)
-{
-       return 32;
-}
-
-static inline int iop_adma_get_max_pq(void)
-{
-       BUG();
-       return 0;
-}
-
-static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
-{
-       int id = chan->device->id;
-
-       switch (id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               return __raw_readl(DMA_DAR(chan));
-       case AAU_ID:
-               return __raw_readl(AAU_ADAR(chan));
-       default:
-               BUG();
-       }
-       return 0;
-}
-
-static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
-                                               u32 next_desc_addr)
-{
-       int id = chan->device->id;
-
-       switch (id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               __raw_writel(next_desc_addr, DMA_NDAR(chan));
-               break;
-       case AAU_ID:
-               __raw_writel(next_desc_addr, AAU_ANDAR(chan));
-               break;
-       }
-
-}
-
-#define IOP_ADMA_STATUS_BUSY (1 << 10)
-#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT (1024)
-#define IOP_ADMA_XOR_MAX_BYTE_COUNT (16 * 1024 * 1024)
-#define IOP_ADMA_MAX_BYTE_COUNT (16 * 1024 * 1024)
-
-static inline int iop_chan_is_busy(struct iop_adma_chan *chan)
-{
-       u32 status = __raw_readl(DMA_CSR(chan));
-       return (status & IOP_ADMA_STATUS_BUSY) ? 1 : 0;
-}
-
-static inline int iop_desc_is_aligned(struct iop_adma_desc_slot *desc,
-                                       int num_slots)
-{
-       /* num_slots will only ever be 1, 2, 4, or 8 */
-       return (desc->idx & (num_slots - 1)) ? 0 : 1;
-}
-
-/* to do: support large (i.e. > hw max) buffer sizes */
-static inline int iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
-{
-       *slots_per_op = 1;
-       return 1;
-}
-
-/* to do: support large (i.e. > hw max) buffer sizes */
-static inline int iop_chan_memset_slot_count(size_t len, int *slots_per_op)
-{
-       *slots_per_op = 1;
-       return 1;
-}
-
-static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
-                                       int *slots_per_op)
-{
-       static const char slot_count_table[] = {
-                                               1, 1, 1, 1, /* 01 - 04 */
-                                               2, 2, 2, 2, /* 05 - 08 */
-                                               4, 4, 4, 4, /* 09 - 12 */
-                                               4, 4, 4, 4, /* 13 - 16 */
-                                               8, 8, 8, 8, /* 17 - 20 */
-                                               8, 8, 8, 8, /* 21 - 24 */
-                                               8, 8, 8, 8, /* 25 - 28 */
-                                               8, 8, 8, 8, /* 29 - 32 */
-                                             };
-       *slots_per_op = slot_count_table[src_cnt - 1];
-       return *slots_per_op;
-}
-
-static inline int
-iop_chan_interrupt_slot_count(int *slots_per_op, struct iop_adma_chan *chan)
-{
-       switch (chan->device->id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               return iop_chan_memcpy_slot_count(0, slots_per_op);
-       case AAU_ID:
-               return iop3xx_aau_xor_slot_count(0, 2, slots_per_op);
-       default:
-               BUG();
-       }
-       return 0;
-}
-
-static inline int iop_chan_xor_slot_count(size_t len, int src_cnt,
-                                               int *slots_per_op)
-{
-       int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
-
-       if (len <= IOP_ADMA_XOR_MAX_BYTE_COUNT)
-               return slot_cnt;
-
-       len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
-       while (len > IOP_ADMA_XOR_MAX_BYTE_COUNT) {
-               len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
-               slot_cnt += *slots_per_op;
-       }
-
-       slot_cnt += *slots_per_op;
-
-       return slot_cnt;
-}
-
-/* zero sum on iop3xx is limited to 1k at a time so it requires multiple
- * descriptors
- */
-static inline int iop_chan_zero_sum_slot_count(size_t len, int src_cnt,
-                                               int *slots_per_op)
-{
-       int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
-
-       if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT)
-               return slot_cnt;
-
-       len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
-       while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
-               len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
-               slot_cnt += *slots_per_op;
-       }
-
-       slot_cnt += *slots_per_op;
-
-       return slot_cnt;
-}
-
-static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
-                                       struct iop_adma_chan *chan)
-{
-       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-
-       switch (chan->device->id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               return hw_desc.dma->byte_count;
-       case AAU_ID:
-               return hw_desc.aau->byte_count;
-       default:
-               BUG();
-       }
-       return 0;
-}
-
-/* translate the src_idx to a descriptor word index */
-static inline int __desc_idx(int src_idx)
-{
-       static const int desc_idx_table[] = { 0, 0, 0, 0,
-                                             0, 1, 2, 3,
-                                             5, 6, 7, 8,
-                                             9, 10, 11, 12,
-                                             14, 15, 16, 17,
-                                             18, 19, 20, 21,
-                                             23, 24, 25, 26,
-                                             27, 28, 29, 30,
-                                           };
-
-       return desc_idx_table[src_idx];
-}
-
-static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
-                                       struct iop_adma_chan *chan,
-                                       int src_idx)
-{
-       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-
-       switch (chan->device->id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               return hw_desc.dma->src_addr;
-       case AAU_ID:
-               break;
-       default:
-               BUG();
-       }
-
-       if (src_idx < 4)
-               return hw_desc.aau->src[src_idx];
-       else
-               return hw_desc.aau->src_edc[__desc_idx(src_idx)].src_addr;
-}
-
-static inline void iop3xx_aau_desc_set_src_addr(struct iop3xx_desc_aau *hw_desc,
-                                       int src_idx, dma_addr_t addr)
-{
-       if (src_idx < 4)
-               hw_desc->src[src_idx] = addr;
-       else
-               hw_desc->src_edc[__desc_idx(src_idx)].src_addr = addr;
-}
-
-static inline void
-iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, unsigned long flags)
-{
-       struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
-       union {
-               u32 value;
-               struct iop3xx_dma_desc_ctrl field;
-       } u_desc_ctrl;
-
-       u_desc_ctrl.value = 0;
-       u_desc_ctrl.field.mem_to_mem_en = 1;
-       u_desc_ctrl.field.pci_transaction = 0xe; /* memory read block */
-       u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
-       hw_desc->desc_ctrl = u_desc_ctrl.value;
-       hw_desc->upper_pci_src_addr = 0;
-       hw_desc->crc_addr = 0;
-}
-
-static inline void
-iop_desc_init_memset(struct iop_adma_desc_slot *desc, unsigned long flags)
-{
-       struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
-       union {
-               u32 value;
-               struct iop3xx_aau_desc_ctrl field;
-       } u_desc_ctrl;
-
-       u_desc_ctrl.value = 0;
-       u_desc_ctrl.field.blk1_cmd_ctrl = 0x2; /* memory block fill */
-       u_desc_ctrl.field.dest_write_en = 1;
-       u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
-       hw_desc->desc_ctrl = u_desc_ctrl.value;
-}
-
-static inline u32
-iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt,
-                    unsigned long flags)
-{
-       int i, shift;
-       u32 edcr;
-       union {
-               u32 value;
-               struct iop3xx_aau_desc_ctrl field;
-       } u_desc_ctrl;
-
-       u_desc_ctrl.value = 0;
-       switch (src_cnt) {
-       case 25 ... 32:
-               u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
-               edcr = 0;
-               shift = 1;
-               for (i = 24; i < src_cnt; i++) {
-                       edcr |= (1 << shift);
-                       shift += 3;
-               }
-               hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = edcr;
-               src_cnt = 24;
-               fallthrough;
-       case 17 ... 24:
-               if (!u_desc_ctrl.field.blk_ctrl) {
-                       hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
-                       u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
-               }
-               edcr = 0;
-               shift = 1;
-               for (i = 16; i < src_cnt; i++) {
-                       edcr |= (1 << shift);
-                       shift += 3;
-               }
-               hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = edcr;
-               src_cnt = 16;
-               fallthrough;
-       case 9 ... 16:
-               if (!u_desc_ctrl.field.blk_ctrl)
-                       u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
-               edcr = 0;
-               shift = 1;
-               for (i = 8; i < src_cnt; i++) {
-                       edcr |= (1 << shift);
-                       shift += 3;
-               }
-               hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = edcr;
-               src_cnt = 8;
-               fallthrough;
-       case 2 ... 8:
-               shift = 1;
-               for (i = 0; i < src_cnt; i++) {
-                       u_desc_ctrl.value |= (1 << shift);
-                       shift += 3;
-               }
-
-               if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
-                       u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
-       }
-
-       u_desc_ctrl.field.dest_write_en = 1;
-       u_desc_ctrl.field.blk1_cmd_ctrl = 0x7; /* direct fill */
-       u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
-       hw_desc->desc_ctrl = u_desc_ctrl.value;
-
-       return u_desc_ctrl.value;
-}
-
-static inline void
-iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt,
-                 unsigned long flags)
-{
-       iop3xx_desc_init_xor(desc->hw_desc, src_cnt, flags);
-}
-
-/* return the number of operations */
-static inline int
-iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt,
-                      unsigned long flags)
-{
-       int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
-       struct iop3xx_desc_aau *hw_desc, *prev_hw_desc, *iter;
-       union {
-               u32 value;
-               struct iop3xx_aau_desc_ctrl field;
-       } u_desc_ctrl;
-       int i, j;
-
-       hw_desc = desc->hw_desc;
-
-       for (i = 0, j = 0; (slot_cnt -= slots_per_op) >= 0;
-               i += slots_per_op, j++) {
-               iter = iop_hw_desc_slot_idx(hw_desc, i);
-               u_desc_ctrl.value = iop3xx_desc_init_xor(iter, src_cnt, flags);
-               u_desc_ctrl.field.dest_write_en = 0;
-               u_desc_ctrl.field.zero_result_en = 1;
-               u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
-               iter->desc_ctrl = u_desc_ctrl.value;
-
-               /* for the subsequent descriptors preserve the store queue
-                * and chain them together
-                */
-               if (i) {
-                       prev_hw_desc =
-                               iop_hw_desc_slot_idx(hw_desc, i - slots_per_op);
-                       prev_hw_desc->next_desc =
-                               (u32) (desc->async_tx.phys + (i << 5));
-               }
-       }
-
-       return j;
-}
-
-static inline void
-iop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt,
-                      unsigned long flags)
-{
-       struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
-       union {
-               u32 value;
-               struct iop3xx_aau_desc_ctrl field;
-       } u_desc_ctrl;
-
-       u_desc_ctrl.value = 0;
-       switch (src_cnt) {
-       case 25 ... 32:
-               u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
-               hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
-               fallthrough;
-       case 17 ... 24:
-               if (!u_desc_ctrl.field.blk_ctrl) {
-                       hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
-                       u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
-               }
-               hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = 0;
-               fallthrough;
-       case 9 ... 16:
-               if (!u_desc_ctrl.field.blk_ctrl)
-                       u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
-               hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = 0;
-               fallthrough;
-       case 1 ... 8:
-               if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
-                       u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
-       }
-
-       u_desc_ctrl.field.dest_write_en = 0;
-       u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
-       hw_desc->desc_ctrl = u_desc_ctrl.value;
-}
-
-static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
-                                       struct iop_adma_chan *chan,
-                                       u32 byte_count)
-{
-       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-
-       switch (chan->device->id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               hw_desc.dma->byte_count = byte_count;
-               break;
-       case AAU_ID:
-               hw_desc.aau->byte_count = byte_count;
-               break;
-       default:
-               BUG();
-       }
-}
-
-static inline void
-iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
-                       struct iop_adma_chan *chan)
-{
-       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-
-       switch (chan->device->id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               iop_desc_init_memcpy(desc, 1);
-               hw_desc.dma->byte_count = 0;
-               hw_desc.dma->dest_addr = 0;
-               hw_desc.dma->src_addr = 0;
-               break;
-       case AAU_ID:
-               iop_desc_init_null_xor(desc, 2, 1);
-               hw_desc.aau->byte_count = 0;
-               hw_desc.aau->dest_addr = 0;
-               hw_desc.aau->src[0] = 0;
-               hw_desc.aau->src[1] = 0;
-               break;
-       default:
-               BUG();
-       }
-}
-
-static inline void
-iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
-{
-       int slots_per_op = desc->slots_per_op;
-       struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
-       int i = 0;
-
-       if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
-               hw_desc->byte_count = len;
-       } else {
-               do {
-                       iter = iop_hw_desc_slot_idx(hw_desc, i);
-                       iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
-                       len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
-                       i += slots_per_op;
-               } while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
-
-               iter = iop_hw_desc_slot_idx(hw_desc, i);
-               iter->byte_count = len;
-       }
-}
-
-static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
-                                       struct iop_adma_chan *chan,
-                                       dma_addr_t addr)
-{
-       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-
-       switch (chan->device->id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               hw_desc.dma->dest_addr = addr;
-               break;
-       case AAU_ID:
-               hw_desc.aau->dest_addr = addr;
-               break;
-       default:
-               BUG();
-       }
-}
-
-static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
-                                       dma_addr_t addr)
-{
-       struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
-       hw_desc->src_addr = addr;
-}
-
-static inline void
-iop_desc_set_zero_sum_src_addr(struct iop_adma_desc_slot *desc, int src_idx,
-                               dma_addr_t addr)
-{
-
-       struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
-       int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
-       int i;
-
-       for (i = 0; (slot_cnt -= slots_per_op) >= 0;
-               i += slots_per_op, addr += IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
-               iter = iop_hw_desc_slot_idx(hw_desc, i);
-               iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
-       }
-}
-
-static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
-                                       int src_idx, dma_addr_t addr)
-{
-
-       struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
-       int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
-       int i;
-
-       for (i = 0; (slot_cnt -= slots_per_op) >= 0;
-               i += slots_per_op, addr += IOP_ADMA_XOR_MAX_BYTE_COUNT) {
-               iter = iop_hw_desc_slot_idx(hw_desc, i);
-               iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
-       }
-}
-
-static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
-                                       u32 next_desc_addr)
-{
-       /* hw_desc->next_desc is the same location for all channels */
-       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-
-       iop_paranoia(hw_desc.dma->next_desc);
-       hw_desc.dma->next_desc = next_desc_addr;
-}
-
-static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
-{
-       /* hw_desc->next_desc is the same location for all channels */
-       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-       return hw_desc.dma->next_desc;
-}
-
-static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
-{
-       /* hw_desc->next_desc is the same location for all channels */
-       union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
-       hw_desc.dma->next_desc = 0;
-}
-
-static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
-                                               u32 val)
-{
-       struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
-       hw_desc->src[0] = val;
-}
-
-static inline enum sum_check_flags
-iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
-{
-       struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
-       struct iop3xx_aau_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
-
-       iop_paranoia(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en));
-       return desc_ctrl.zero_result_err << SUM_CHECK_P;
-}
-
-static inline void iop_chan_append(struct iop_adma_chan *chan)
-{
-       u32 dma_chan_ctrl;
-
-       dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
-       dma_chan_ctrl |= 0x2;
-       __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
-}
-
-static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
-{
-       return __raw_readl(DMA_CSR(chan));
-}
-
-static inline void iop_chan_disable(struct iop_adma_chan *chan)
-{
-       u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
-       dma_chan_ctrl &= ~1;
-       __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
-}
-
-static inline void iop_chan_enable(struct iop_adma_chan *chan)
-{
-       u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
-
-       dma_chan_ctrl |= 1;
-       __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
-}
-
-static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
-{
-       u32 status = __raw_readl(DMA_CSR(chan));
-       status &= (1 << 9);
-       __raw_writel(status, DMA_CSR(chan));
-}
-
-static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
-{
-       u32 status = __raw_readl(DMA_CSR(chan));
-       status &= (1 << 8);
-       __raw_writel(status, DMA_CSR(chan));
-}
-
-static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
-{
-       u32 status = __raw_readl(DMA_CSR(chan));
-
-       switch (chan->device->id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               status &= (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1);
-               break;
-       case AAU_ID:
-               status &= (1 << 5);
-               break;
-       default:
-               BUG();
-       }
-
-       __raw_writel(status, DMA_CSR(chan));
-}
-
-static inline int
-iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
-{
-       return 0;
-}
-
-static inline int
-iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
-{
-       return 0;
-}
-
-static inline int
-iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
-{
-       return 0;
-}
-
-static inline int
-iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
-{
-       return test_bit(5, &status);
-}
-
-static inline int
-iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
-{
-       switch (chan->device->id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               return test_bit(2, &status);
-       default:
-               return 0;
-       }
-}
-
-static inline int
-iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
-{
-       switch (chan->device->id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               return test_bit(3, &status);
-       default:
-               return 0;
-       }
-}
-
-static inline int
-iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
-{
-       switch (chan->device->id) {
-       case DMA0_ID:
-       case DMA1_ID:
-               return test_bit(1, &status);
-       default:
-               return 0;
-       }
-}
-#endif /* _ADMA_H */
index 3f56514bbef8f9d3178b2a67fdaf2fb6e0bb530d..061add83229512e07f6ed90701789e395f02522d 100644 (file)
@@ -2286,9 +2286,14 @@ static int gpi_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id gpi_of_match[] = {
-       { .compatible = "qcom,sc7280-gpi-dma", .data = (void *)0x10000 },
        { .compatible = "qcom,sdm845-gpi-dma", .data = (void *)0x0 },
        { .compatible = "qcom,sm6350-gpi-dma", .data = (void *)0x10000 },
+       /*
+        * Do not grow the list for compatible devices. Instead use
+        * qcom,sdm845-gpi-dma (for ee_offset = 0x0) or qcom,sm6350-gpi-dma
+        * (for ee_offset = 0x10000).
+        */
+       { .compatible = "qcom,sc7280-gpi-dma", .data = (void *)0x10000 },
        { .compatible = "qcom,sm8150-gpi-dma", .data = (void *)0x0 },
        { .compatible = "qcom,sm8250-gpi-dma", .data = (void *)0x0 },
        { .compatible = "qcom,sm8350-gpi-dma", .data = (void *)0x10000 },
diff --git a/drivers/dma/sh/shdma-arm.h b/drivers/dma/sh/shdma-arm.h
deleted file mode 100644 (file)
index 7459f9a..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Renesas SuperH DMA Engine support
- *
- * Copyright (C) 2013 Renesas Electronics, Inc.
- */
-
-#ifndef SHDMA_ARM_H
-#define SHDMA_ARM_H
-
-#include "shdma.h"
-
-/* Transmit sizes and respective CHCR register values */
-enum {
-       XMIT_SZ_8BIT            = 0,
-       XMIT_SZ_16BIT           = 1,
-       XMIT_SZ_32BIT           = 2,
-       XMIT_SZ_64BIT           = 7,
-       XMIT_SZ_128BIT          = 3,
-       XMIT_SZ_256BIT          = 4,
-       XMIT_SZ_512BIT          = 5,
-};
-
-/* log2(size / 8) - used to calculate number of transfers */
-#define SH_DMAE_TS_SHIFT {             \
-       [XMIT_SZ_8BIT]          = 0,    \
-       [XMIT_SZ_16BIT]         = 1,    \
-       [XMIT_SZ_32BIT]         = 2,    \
-       [XMIT_SZ_64BIT]         = 3,    \
-       [XMIT_SZ_128BIT]        = 4,    \
-       [XMIT_SZ_256BIT]        = 5,    \
-       [XMIT_SZ_512BIT]        = 6,    \
-}
-
-#define TS_LOW_BIT     0x3 /* --xx */
-#define TS_HI_BIT      0xc /* xx-- */
-
-#define TS_LOW_SHIFT   (3)
-#define TS_HI_SHIFT    (20 - 2)        /* 2 bits for shifted low TS */
-
-#define TS_INDEX2VAL(i) \
-       ((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\
-        (((i) & TS_HI_BIT)  << TS_HI_SHIFT))
-
-#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | RS_ERS | TS_INDEX2VAL((xmit_sz)))
-#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | RS_ERS | TS_INDEX2VAL((xmit_sz)))
-
-#endif
index fa9bda4a2bc6fe4453276fdca95c6194eaca84bb..1d1180db6d4ecdca4e540da718fcf733aa42438f 100644 (file)
 #define TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT  5000 /* 5 msec */
 
 /* Channel base address offset from GPCDMA base address */
-#define TEGRA_GPCDMA_CHANNEL_BASE_ADD_OFFSET   0x20000
+#define TEGRA_GPCDMA_CHANNEL_BASE_ADDR_OFFSET  0x10000
+
+/* Default channel mask reserving channel0 */
+#define TEGRA_GPCDMA_DEFAULT_CHANNEL_MASK      0xfffffffe
 
 struct tegra_dma;
 struct tegra_dma_channel;
@@ -246,6 +249,7 @@ struct tegra_dma {
        const struct tegra_dma_chip_data *chip_data;
        unsigned long sid_m2d_reserved;
        unsigned long sid_d2m_reserved;
+       u32 chan_mask;
        void __iomem *base_addr;
        struct device *dev;
        struct dma_device dma_dev;
@@ -1288,7 +1292,7 @@ static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
 }
 
 static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
-       .nr_channels = 31,
+       .nr_channels = 32,
        .channel_reg_size = SZ_64K,
        .max_dma_count = SZ_1G,
        .hw_support_pause = false,
@@ -1296,7 +1300,7 @@ static const struct tegra_dma_chip_data tegra186_dma_chip_data = {
 };
 
 static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
-       .nr_channels = 31,
+       .nr_channels = 32,
        .channel_reg_size = SZ_64K,
        .max_dma_count = SZ_1G,
        .hw_support_pause = true,
@@ -1304,7 +1308,7 @@ static const struct tegra_dma_chip_data tegra194_dma_chip_data = {
 };
 
 static const struct tegra_dma_chip_data tegra234_dma_chip_data = {
-       .nr_channels = 31,
+       .nr_channels = 32,
        .channel_reg_size = SZ_64K,
        .max_dma_count = SZ_1G,
        .hw_support_pause = true,
@@ -1380,15 +1384,28 @@ static int tegra_dma_probe(struct platform_device *pdev)
        }
        stream_id = iommu_spec->ids[0] & 0xffff;
 
+       ret = device_property_read_u32(&pdev->dev, "dma-channel-mask",
+                                      &tdma->chan_mask);
+       if (ret) {
+               dev_warn(&pdev->dev,
+                        "Missing dma-channel-mask property, using default channel mask %#x\n",
+                        TEGRA_GPCDMA_DEFAULT_CHANNEL_MASK);
+               tdma->chan_mask = TEGRA_GPCDMA_DEFAULT_CHANNEL_MASK;
+       }
+
        INIT_LIST_HEAD(&tdma->dma_dev.channels);
        for (i = 0; i < cdata->nr_channels; i++) {
                struct tegra_dma_channel *tdc = &tdma->channels[i];
 
+               /* Check for channel mask */
+               if (!(tdma->chan_mask & BIT(i)))
+                       continue;
+
                tdc->irq = platform_get_irq(pdev, i);
                if (tdc->irq < 0)
                        return tdc->irq;
 
-               tdc->chan_base_offset = TEGRA_GPCDMA_CHANNEL_BASE_ADD_OFFSET +
+               tdc->chan_base_offset = TEGRA_GPCDMA_CHANNEL_BASE_ADDR_OFFSET +
                                        i * cdata->channel_reg_size;
                snprintf(tdc->name, sizeof(tdc->name), "gpcdma.%d", i);
                tdc->tdma = tdma;
@@ -1449,8 +1466,8 @@ static int tegra_dma_probe(struct platform_device *pdev)
                return ret;
        }
 
-       dev_info(&pdev->dev, "GPC DMA driver register %d channels\n",
-                cdata->nr_channels);
+       dev_info(&pdev->dev, "GPC DMA driver register %lu channels\n",
+                hweight_long(tdma->chan_mask));
 
        return 0;
 }
@@ -1473,6 +1490,9 @@ static int __maybe_unused tegra_dma_pm_suspend(struct device *dev)
        for (i = 0; i < tdma->chip_data->nr_channels; i++) {
                struct tegra_dma_channel *tdc = &tdma->channels[i];
 
+               if (!(tdma->chan_mask & BIT(i)))
+                       continue;
+
                if (tdc->dma_desc) {
                        dev_err(tdma->dev, "channel %u busy\n", i);
                        return -EBUSY;
@@ -1492,6 +1512,9 @@ static int __maybe_unused tegra_dma_pm_resume(struct device *dev)
        for (i = 0; i < tdma->chip_data->nr_channels; i++) {
                struct tegra_dma_channel *tdc = &tdma->channels[i];
 
+               if (!(tdma->chan_mask & BIT(i)))
+                       continue;
+
                tegra_dma_program_sid(tdc, tdc->stream_id);
        }
 
index 79618fac119a7259a36528e5537268c976f0e8ba..2adc2cca10e926b5a2be57a3271ee6374ff9e297 100644 (file)
@@ -35,7 +35,7 @@ config DMA_OMAP
          DMA engine is found on OMAP and DRA7xx parts.
 
 config TI_K3_UDMA
-       bool "Texas Instruments UDMA support"
+       tristate "Texas Instruments UDMA support"
        depends on ARCH_K3
        depends on TI_SCI_PROTOCOL
        depends on TI_SCI_INTA_IRQCHIP
@@ -48,7 +48,7 @@ config TI_K3_UDMA
          DMA engine is used in AM65x and j721e.
 
 config TI_K3_UDMA_GLUE_LAYER
-       bool "Texas Instruments UDMA Glue layer for non DMAengine users"
+       tristate "Texas Instruments UDMA Glue layer for non DMAengine users"
        depends on ARCH_K3
        depends on TI_K3_UDMA
        help
@@ -56,7 +56,8 @@ config TI_K3_UDMA_GLUE_LAYER
          If unsure, say N.
 
 config TI_K3_PSIL
-       bool
+       tristate
+       default TI_K3_UDMA
 
 config TI_DMA_CROSSBAR
        bool
index d3a303f0d7c621b962af3cb56401fa10c1126e89..b53d05b11ca5ef9a2cb840db6a693a244bb91a08 100644 (file)
@@ -4,11 +4,12 @@ obj-$(CONFIG_TI_EDMA) += edma.o
 obj-$(CONFIG_DMA_OMAP) += omap-dma.o
 obj-$(CONFIG_TI_K3_UDMA) += k3-udma.o
 obj-$(CONFIG_TI_K3_UDMA_GLUE_LAYER) += k3-udma-glue.o
-obj-$(CONFIG_TI_K3_PSIL) += k3-psil.o \
-                           k3-psil-am654.o \
-                           k3-psil-j721e.o \
-                           k3-psil-j7200.o \
-                           k3-psil-am64.o \
-                           k3-psil-j721s2.o \
-                           k3-psil-am62.o
+k3-psil-lib-objs := k3-psil.o \
+                   k3-psil-am654.o \
+                   k3-psil-j721e.o \
+                   k3-psil-j7200.o \
+                   k3-psil-am64.o \
+                   k3-psil-j721s2.o \
+                   k3-psil-am62.o
+obj-$(CONFIG_TI_K3_PSIL) += k3-psil-lib.o
 obj-$(CONFIG_TI_DMA_CROSSBAR) += dma-crossbar.o
index 761a384093d20e6345283331be3975a42246f593..8b6533a1eeeb99c0525c1dadd1135cfe5a8d7abc 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
@@ -101,3 +102,4 @@ int psil_set_new_ep_config(struct device *dev, const char *name,
        return 0;
 }
 EXPORT_SYMBOL_GPL(psil_set_new_ep_config);
+MODULE_LICENSE("GPL v2");
index 4f1aeb81e9c7f280bec0a55b98eaa5c7e1013912..789193ed038650b5d73f64fd8db8cab84c031936 100644 (file)
@@ -6,6 +6,7 @@
  *
  */
 
+#include <linux/module.h>
 #include <linux/atomic.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
@@ -1436,4 +1437,6 @@ static int __init k3_udma_glue_class_init(void)
 {
        return class_register(&k3_udma_glue_devclass);
 }
-arch_initcall(k3_udma_glue_class_init);
+
+module_init(k3_udma_glue_class_init);
+MODULE_LICENSE("GPL v2");
index 7b5081989b3d6f76b6657b901362fc219ffd7396..ce8b80bb34d7d1f2f0d1c537d776cda691590193 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
@@ -4335,18 +4336,10 @@ static const struct of_device_id udma_of_match[] = {
                .compatible = "ti,j721e-navss-mcu-udmap",
                .data = &j721e_mcu_data,
        },
-       { /* Sentinel */ },
-};
-
-static const struct of_device_id bcdma_of_match[] = {
        {
                .compatible = "ti,am64-dmss-bcdma",
                .data = &am64_bcdma_data,
        },
-       { /* Sentinel */ },
-};
-
-static const struct of_device_id pktdma_of_match[] = {
        {
                .compatible = "ti,am64-dmss-pktdma",
                .data = &am64_pktdma_data,
@@ -5271,14 +5264,9 @@ static int udma_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        match = of_match_node(udma_of_match, dev->of_node);
-       if (!match)
-               match = of_match_node(bcdma_of_match, dev->of_node);
        if (!match) {
-               match = of_match_node(pktdma_of_match, dev->of_node);
-               if (!match) {
-                       dev_err(dev, "No compatible match found\n");
-                       return -ENODEV;
-               }
+               dev_err(dev, "No compatible match found\n");
+               return -ENODEV;
        }
        ud->match_data = match->data;
 
@@ -5511,27 +5499,9 @@ static struct platform_driver udma_driver = {
        },
        .probe          = udma_probe,
 };
-builtin_platform_driver(udma_driver);
 
-static struct platform_driver bcdma_driver = {
-       .driver = {
-               .name   = "ti-bcdma",
-               .of_match_table = bcdma_of_match,
-               .suppress_bind_attrs = true,
-       },
-       .probe          = udma_probe,
-};
-builtin_platform_driver(bcdma_driver);
-
-static struct platform_driver pktdma_driver = {
-       .driver = {
-               .name   = "ti-pktdma",
-               .of_match_table = pktdma_of_match,
-               .suppress_bind_attrs = true,
-       },
-       .probe          = udma_probe,
-};
-builtin_platform_driver(pktdma_driver);
+module_platform_driver(udma_driver);
+MODULE_LICENSE("GPL v2");
 
 /* Private interfaces to UDMA */
 #include "k3-udma-private.c"
index 8cd4e69dc7b4c24b334c450562c2a88925b0f452..a8d23cdf883e5b825a3a66576903b1043280deae 100644 (file)
@@ -1659,6 +1659,8 @@ static void xilinx_dma_issue_pending(struct dma_chan *dchan)
  * xilinx_dma_device_config - Configure the DMA channel
  * @dchan: DMA channel
  * @config: channel configuration
+ *
+ * Return: 0 always.
  */
 static int xilinx_dma_device_config(struct dma_chan *dchan,
                                    struct dma_slave_config *config)
@@ -2924,7 +2926,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
  * @xdev: Driver specific device structure
  * @node: Device node
  *
- * Return: 0 always.
+ * Return: '0' on success and failure value on error.
  */
 static int xilinx_dma_child_probe(struct xilinx_dma_device *xdev,
                                    struct device_node *node)
index 2bac44f09554b146fdc5a20435f2fcd60a585ca7..e9bf5236ed892765f33a1ae4e8ff6c8b0ab53aca 100644 (file)
@@ -730,6 +730,7 @@ struct irq_domain *of_msi_get_domain(struct device *dev,
 
        return NULL;
 }
+EXPORT_SYMBOL_GPL(of_msi_get_domain);
 
 /**
  * of_msi_configure - Set the msi_domain field of a device
index 2b9e7feba3f32ed84dcc0bdbc1d85128298f4ec7..1d553bedbdb515147b767479a06469ca7c048ef9 100644 (file)
@@ -295,7 +295,7 @@ struct dsa_completion_record {
                };
 
                uint32_t        delta_rec_size;
-               uint32_t        crc_val;
+               uint64_t        crc_val;
 
                /* DIF check & strip */
                struct {