Merge tag 'dmaengine-5.4-rc1' of git://git.infradead.org/users/vkoul/slave-dma
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 18 Sep 2019 02:04:40 +0000 (19:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 18 Sep 2019 02:04:40 +0000 (19:04 -0700)
Pull dmaengine updates from Vinod Koul:

 - Move Dmaengine DT bindings to YAML and convert Allwinner to schema.

 - FSL dma device_synchronize implementation

 - DW split acpi and of helpers and updates to driver and support for
   Elkhart Lake

 - Move filter fn as private for omap-dma and edma drivers and
   improvements to these drivers

 - Mark expected switch fall-through in couple of drivers

 - Renames of shdma and nbpfaxi binding document

 - Minor updates to bunch of drivers

* tag 'dmaengine-5.4-rc1' of git://git.infradead.org/users/vkoul/slave-dma: (55 commits)
  dmaengine: ti: edma: Use bitmap_set() instead of open coded edma_set_bits()
  dmaengine: ti: edma: Only reset region0 access registers
  dmaengine: ti: edma: Do not reset reserved paRAM slots
  dmaengine: iop-adma.c: fix printk format warning
  dmaengine: stm32-dma: Use struct_size() helper
  dt-bindings: dmaengine: dma-common: Fix the dma-channel-mask property
  dmanegine: ioat/dca: Use struct_size() helper
  dmaengine: iop-adma: remove set but not used variable 'slots_per_op'
  dmaengine: dmatest: Add support for completion polling
  dmaengine: ti: omap-dma: Remove variable override in omap_dma_tx_status()
  dmaengine: ti: omap-dma: Remove 'Assignment in if condition'
  dmaengine: ti: edma: Remove 'Assignment in if condition'
  dmaengine: dw: platform: Split OF helpers to separate module
  dmaengine: dw: platform: Split ACPI helpers to separate module
  dmaengine: dw: platform: Move handle check to dw_dma_acpi_controller_register()
  dmaengine: dw: platform: Switch to acpi_dma_controller_register()
  dmaengine: dw: platform: Use devm_platform_ioremap_resource()
  dmaengine: dw: platform: Enable iDMA 32-bit on Intel Elkhart Lake
  dmaengine: dw: platform: Use struct dw_dma_chip_pdata
  dmaengine: dw: Export struct dw_dma_chip_pdata for wider use
  ...

56 files changed:
Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/dma/dma-common.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/dma/dma-controller.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/dma/dma-router.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/dma/dma.txt
Documentation/devicetree/bindings/dma/nbpfaxi.txt [deleted file]
Documentation/devicetree/bindings/dma/renesas,nbpfaxi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/dma/renesas,shdma.txt [new file with mode: 0644]
Documentation/devicetree/bindings/dma/shdma.txt [deleted file]
Documentation/devicetree/bindings/dma/sun4i-dma.txt [deleted file]
Documentation/devicetree/bindings/dma/sun6i-dma.txt [deleted file]
MAINTAINERS
drivers/dma/Kconfig
drivers/dma/acpi-dma.c
drivers/dma/bcm2835-dma.c
drivers/dma/dma-jz4780.c
drivers/dma/dmatest.c
drivers/dma/dw/Makefile
drivers/dma/dw/acpi.c [new file with mode: 0644]
drivers/dma/dw/internal.h
drivers/dma/dw/of.c [new file with mode: 0644]
drivers/dma/dw/pci.c
drivers/dma/dw/platform.c
drivers/dma/fsl-edma-common.c
drivers/dma/fsl-edma-common.h
drivers/dma/fsl-edma.c
drivers/dma/fsl-qdma.c
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/ioat/dca.c
drivers/dma/iop-adma.c
drivers/dma/mediatek/mtk-uart-apdma.c
drivers/dma/mv_xor_v2.c
drivers/dma/pl330.c
drivers/dma/qcom/hidma_ll.c
drivers/dma/qcom/hidma_mgmt.c
drivers/dma/s3c24xx-dma.c
drivers/dma/sh/rcar-dmac.c
drivers/dma/sh/usb-dmac.c
drivers/dma/st_fdma.c
drivers/dma/stm32-dma.c
drivers/dma/stm32-dmamux.c
drivers/dma/stm32-mdma.c
drivers/dma/sun4i-dma.c
drivers/dma/sun6i-dma.c
drivers/dma/tegra20-apb-dma.c
drivers/dma/tegra210-adma.c
drivers/dma/ti/edma.c
drivers/dma/ti/omap-dma.c
drivers/dma/uniphier-mdmac.c
drivers/dma/xgene-dma.c
include/linux/edma.h [deleted file]
include/linux/omap-dma.h
include/linux/omap-dmaengine.h [deleted file]

diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml
new file mode 100644 (file)
index 0000000..15abc0f
--- /dev/null
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/allwinner,sun4i-a10-dma.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A10 DMA Controller Device Tree Bindings
+
+maintainers:
+  - Chen-Yu Tsai <wens@csie.org>
+  - Maxime Ripard <maxime.ripard@bootlin.com>
+
+allOf:
+  - $ref: "dma-controller.yaml#"
+
+properties:
+  "#dma-cells":
+    const: 2
+    description:
+      The first cell is either 0 or 1, the former to use the normal
+      DMA, 1 for dedicated DMA. The second cell is the request line
+      number.
+
+  compatible:
+    const: allwinner,sun4i-a10-dma
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+required:
+  - "#dma-cells"
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    dma: dma-controller@1c02000 {
+        compatible = "allwinner,sun4i-a10-dma";
+        reg = <0x01c02000 0x1000>;
+        interrupts = <27>;
+        clocks = <&ahb_gates 6>;
+        #dma-cells = <2>;
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
new file mode 100644 (file)
index 0000000..4cb9d6b
--- /dev/null
@@ -0,0 +1,88 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/allwinner,sun50i-a64-dma.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A64 DMA Controller Device Tree Bindings
+
+maintainers:
+  - Chen-Yu Tsai <wens@csie.org>
+  - Maxime Ripard <maxime.ripard@bootlin.com>
+
+allOf:
+  - $ref: "dma-controller.yaml#"
+
+properties:
+  "#dma-cells":
+    const: 1
+    description: The cell is the request line number.
+
+  compatible:
+    enum:
+      - allwinner,sun50i-a64-dma
+      - allwinner,sun50i-h6-dma
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    minItems: 1
+    maxItems: 2
+
+  clock-names:
+    items:
+      - const: bus
+      - const: mbus
+
+  resets:
+    maxItems: 1
+
+required:
+  - "#dma-cells"
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - resets
+  - dma-channels
+
+if:
+  properties:
+    compatible:
+      const: allwinner,sun50i-h6-dma
+
+then:
+  properties:
+    clocks:
+      maxItems: 2
+
+  required:
+    - clock-names
+
+else:
+  properties:
+    clocks:
+      maxItems: 1
+
+# FIXME: We should set it, but it would report all the generic
+# properties as additional properties.
+# additionalProperties: false
+
+examples:
+  - |
+    dma: dma-controller@1c02000 {
+        compatible = "allwinner,sun50i-a64-dma";
+        reg = <0x01c02000 0x1000>;
+        interrupts = <0 50 4>;
+        clocks = <&ccu 30>;
+        dma-channels = <8>;
+        dma-requests = <27>;
+        resets = <&ccu 7>;
+        #dma-cells = <1>;
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml
new file mode 100644 (file)
index 0000000..740b7f9
--- /dev/null
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/allwinner,sun6i-a31-dma.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A31 DMA Controller Device Tree Bindings
+
+maintainers:
+  - Chen-Yu Tsai <wens@csie.org>
+  - Maxime Ripard <maxime.ripard@bootlin.com>
+
+allOf:
+  - $ref: "dma-controller.yaml#"
+
+properties:
+  "#dma-cells":
+    const: 1
+    description: The cell is the request line number.
+
+  compatible:
+    oneOf:
+      - const: allwinner,sun6i-a31-dma
+      - const: allwinner,sun8i-a23-dma
+      - const: allwinner,sun8i-a83t-dma
+      - const: allwinner,sun8i-h3-dma
+      - const: allwinner,sun8i-v3s-dma
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+required:
+  - "#dma-cells"
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - resets
+
+additionalProperties: false
+
+examples:
+  - |
+    dma: dma-controller@1c02000 {
+        compatible = "allwinner,sun6i-a31-dma";
+        reg = <0x01c02000 0x1000>;
+        interrupts = <0 50 4>;
+        clocks = <&ahb1_gates 6>;
+        resets = <&ahb1_rst 6>;
+        #dma-cells = <1>;
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/dma/dma-common.yaml b/Documentation/devicetree/bindings/dma/dma-common.yaml
new file mode 100644 (file)
index 0000000..ed0a49a
--- /dev/null
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/dma-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: DMA Engine Generic Binding
+
+maintainers:
+  - Vinod Koul <vkoul@kernel.org>
+
+description:
+  Generic binding to provide a way for a driver using DMA Engine to
+  retrieve the DMA request or channel information that goes from a
+  hardware device to a DMA controller.
+
+select: false
+
+properties:
+  "#dma-cells":
+    minimum: 1
+    # Should be enough
+    maximum: 255
+    description:
+      Used to provide DMA controller specific information.
+
+  dma-channel-mask:
+    $ref: /schemas/types.yaml#definitions/uint32
+    description:
+      Bitmask of available DMA channels in ascending order that are
+      not reserved by firmware and are available to the
+      kernel. i.e. first channel corresponds to LSB.
+
+  dma-channels:
+    $ref: /schemas/types.yaml#definitions/uint32
+    description:
+      Number of DMA channels supported by the controller.
+
+  dma-requests:
+    $ref: /schemas/types.yaml#definitions/uint32
+    description:
+      Number of DMA request signals supported by the controller.
+
+required:
+  - "#dma-cells"
diff --git a/Documentation/devicetree/bindings/dma/dma-controller.yaml b/Documentation/devicetree/bindings/dma/dma-controller.yaml
new file mode 100644 (file)
index 0000000..c39f6de
--- /dev/null
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/dma-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: DMA Controller Generic Binding
+
+maintainers:
+  - Vinod Koul <vkoul@kernel.org>
+
+allOf:
+  - $ref: "dma-common.yaml#"
+
+# Everything else is described in the common file
+properties:
+  $nodename:
+    pattern: "^dma-controller(@.*)?$"
+
+examples:
+  - |
+    dma: dma-controller@48000000 {
+        compatible = "ti,omap-sdma";
+        reg = <0x48000000 0x1000>;
+        interrupts = <0 12 0x4
+                      0 13 0x4
+                      0 14 0x4
+                      0 15 0x4>;
+        #dma-cells = <1>;
+        dma-channels = <32>;
+        dma-requests = <127>;
+        dma-channel-mask = <0xfffe>;
+    };
+
+...
diff --git a/Documentation/devicetree/bindings/dma/dma-router.yaml b/Documentation/devicetree/bindings/dma/dma-router.yaml
new file mode 100644 (file)
index 0000000..5b5f073
--- /dev/null
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dma/dma-router.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: DMA Router Generic Binding
+
+maintainers:
+  - Vinod Koul <vkoul@kernel.org>
+
+allOf:
+  - $ref: "dma-common.yaml#"
+
+description:
+  DMA routers are transparent IP blocks used to route DMA request
+  lines from devices to the DMA controller. Some SoCs (like TI DRA7x)
+  have more peripherals integrated with DMA requests than what the DMA
+  controller can handle directly.
+
+properties:
+  $nodename:
+    pattern: "^dma-router(@.*)?$"
+
+  dma-masters:
+    $ref: /schemas/types.yaml#definitions/phandle-array
+    description:
+      Array of phandles to the DMA controllers the router can direct
+      the signal to.
+
+  dma-requests:
+    description:
+      Number of incoming request lines the router can handle.
+
+required:
+  - "#dma-cells"
+  - dma-masters
+
+examples:
+  - |
+    sdma_xbar: dma-router@4a002b78 {
+        compatible = "ti,dra7-dma-crossbar";
+        reg = <0x4a002b78 0xfc>;
+        #dma-cells = <1>;
+        dma-requests = <205>;
+        ti,dma-safe-map = <0>;
+        dma-masters = <&sdma>;
+    };
+
+...
index eeb4e4d1771ed42c33951d6f326f434b0607fb5a..90a67a016a48837386976b938019c2306700782a 100644 (file)
@@ -1,113 +1 @@
-* Generic DMA Controller and DMA request bindings
-
-Generic binding to provide a way for a driver using DMA Engine to retrieve the
-DMA request or channel information that goes from a hardware device to a DMA
-controller.
-
-
-* DMA controller
-
-Required property:
-- #dma-cells:          Must be at least 1. Used to provide DMA controller
-                       specific information. See DMA client binding below for
-                       more details.
-
-Optional properties:
-- dma-channels:        Number of DMA channels supported by the controller.
-- dma-requests:        Number of DMA request signals supported by the
-                       controller.
-- dma-channel-mask:    Bitmask of available DMA channels in ascending order
-                       that are not reserved by firmware and are available to
-                       the kernel. i.e. first channel corresponds to LSB.
-
-Example:
-
-       dma: dma@48000000 {
-               compatible = "ti,omap-sdma";
-               reg = <0x48000000 0x1000>;
-               interrupts = <0 12 0x4
-                             0 13 0x4
-                             0 14 0x4
-                             0 15 0x4>;
-               #dma-cells = <1>;
-               dma-channels = <32>;
-               dma-requests = <127>;
-               dma-channel-mask = <0xfffe>
-       };
-
-* DMA router
-
-DMA routers are transparent IP blocks used to route DMA request lines from
-devices to the DMA controller. Some SoCs (like TI DRA7x) have more peripherals
-integrated with DMA requests than what the DMA controller can handle directly.
-
-Required property:
-- dma-masters:         phandle of the DMA controller or list of phandles for
-                       the DMA controllers the router can direct the signal to.
-- #dma-cells:          Must be at least 1. Used to provide DMA router specific
-                       information. See DMA client binding below for more
-                       details.
-
-Optional properties:
-- dma-requests:        Number of incoming request lines the router can handle.
-- In the node pointed by the dma-masters:
-       - dma-requests: The router driver might need to look for this in order
-                       to configure the routing.
-
-Example:
-       sdma_xbar: dma-router@4a002b78 {
-               compatible = "ti,dra7-dma-crossbar";
-               reg = <0x4a002b78 0xfc>;
-               #dma-cells = <1>;
-               dma-requests = <205>;
-               ti,dma-safe-map = <0>;
-               dma-masters = <&sdma>;
-       };
-
-* DMA client
-
-Client drivers should specify the DMA property using a phandle to the controller
-followed by DMA controller specific data.
-
-Required property:
-- dmas:                        List of one or more DMA specifiers, each consisting of
-                       - A phandle pointing to DMA controller node
-                       - A number of integer cells, as determined by the
-                         #dma-cells property in the node referenced by phandle
-                         containing DMA controller specific information. This
-                         typically contains a DMA request line number or a
-                         channel number, but can contain any data that is
-                         required for configuring a channel.
-- dma-names:           Contains one identifier string for each DMA specifier in
-                       the dmas property. The specific strings that can be used
-                       are defined in the binding of the DMA client device.
-                       Multiple DMA specifiers can be used to represent
-                       alternatives and in this case the dma-names for those
-                       DMA specifiers must be identical (see examples).
-
-Examples:
-
-1. A device with one DMA read channel, one DMA write channel:
-
-       i2c1: i2c@1 {
-               ...
-               dmas = <&dma 2          /* read channel */
-                       &dma 3>;        /* write channel */
-               dma-names = "rx", "tx";
-               ...
-       };
-
-2. A single read-write channel with three alternative DMA controllers:
-
-       dmas = <&dma1 5
-               &dma2 7
-               &dma3 2>;
-       dma-names = "rx-tx", "rx-tx", "rx-tx";
-
-3. A device with three channels, one of which has two alternatives:
-
-       dmas = <&dma1 2                 /* read channel */
-               &dma1 3                 /* write channel */
-               &dma2 0                 /* error read */
-               &dma3 0>;               /* alternative error read */
-       dma-names = "rx", "tx", "error", "error";
+This file has been moved to dma-controller.yaml.
diff --git a/Documentation/devicetree/bindings/dma/nbpfaxi.txt b/Documentation/devicetree/bindings/dma/nbpfaxi.txt
deleted file mode 100644 (file)
index d2e1e62..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-* Renesas "Type-AXI" NBPFAXI* DMA controllers
-
-* DMA controller
-
-Required properties
-
-- compatible:  must be one of
-               "renesas,nbpfaxi64dmac1b4"
-               "renesas,nbpfaxi64dmac1b8"
-               "renesas,nbpfaxi64dmac1b16"
-               "renesas,nbpfaxi64dmac4b4"
-               "renesas,nbpfaxi64dmac4b8"
-               "renesas,nbpfaxi64dmac4b16"
-               "renesas,nbpfaxi64dmac8b4"
-               "renesas,nbpfaxi64dmac8b8"
-               "renesas,nbpfaxi64dmac8b16"
-- #dma-cells:  must be 2: the first integer is a terminal number, to which this
-               slave is connected, the second one is flags. Flags is a bitmask
-               with the following bits defined:
-
-#define NBPF_SLAVE_RQ_HIGH     1
-#define NBPF_SLAVE_RQ_LOW      2
-#define NBPF_SLAVE_RQ_LEVEL    4
-
-Optional properties:
-- max-burst-mem-read:  limit burst size for memory reads
-  (DMA_MEM_TO_MEM/DMA_MEM_TO_DEV) to this value, specified in bytes, rather
-  than using the maximum burst size allowed by the hardware's buffer size.
-- max-burst-mem-write: limit burst size for memory writes
-  (DMA_DEV_TO_MEM/DMA_MEM_TO_MEM) to this value, specified in bytes, rather
-  than using the maximum burst size allowed by the hardware's buffer size.
-  If both max-burst-mem-read and max-burst-mem-write are set, DMA_MEM_TO_MEM
-  will use the lower value.
-
-You can use dma-channels and dma-requests as described in dma.txt, although they
-won't be used, this information is derived from the compatibility string.
-
-Example:
-
-       dma: dma-controller@48000000 {
-               compatible = "renesas,nbpfaxi64dmac8b4";
-               reg = <0x48000000 0x400>;
-               interrupts = <0 12 0x4
-                             0 13 0x4
-                             0 14 0x4
-                             0 15 0x4
-                             0 16 0x4
-                             0 17 0x4
-                             0 18 0x4
-                             0 19 0x4>;
-               #dma-cells = <2>;
-               dma-channels = <8>;
-               dma-requests = <8>;
-       };
-
-* DMA client
-
-Required properties:
-
-dmas and dma-names are required, as described in dma.txt.
-
-Example:
-
-#include <dt-bindings/dma/nbpfaxi.h>
-
-...
-               dmas = <&dma 0 (NBPF_SLAVE_RQ_HIGH | NBPF_SLAVE_RQ_LEVEL)
-                       &dma 1 (NBPF_SLAVE_RQ_HIGH | NBPF_SLAVE_RQ_LEVEL)>;
-               dma-names = "rx", "tx";
diff --git a/Documentation/devicetree/bindings/dma/renesas,nbpfaxi.txt b/Documentation/devicetree/bindings/dma/renesas,nbpfaxi.txt
new file mode 100644 (file)
index 0000000..d2e1e62
--- /dev/null
@@ -0,0 +1,69 @@
+* Renesas "Type-AXI" NBPFAXI* DMA controllers
+
+* DMA controller
+
+Required properties
+
+- compatible:  must be one of
+               "renesas,nbpfaxi64dmac1b4"
+               "renesas,nbpfaxi64dmac1b8"
+               "renesas,nbpfaxi64dmac1b16"
+               "renesas,nbpfaxi64dmac4b4"
+               "renesas,nbpfaxi64dmac4b8"
+               "renesas,nbpfaxi64dmac4b16"
+               "renesas,nbpfaxi64dmac8b4"
+               "renesas,nbpfaxi64dmac8b8"
+               "renesas,nbpfaxi64dmac8b16"
+- #dma-cells:  must be 2: the first integer is a terminal number, to which this
+               slave is connected, the second one is flags. Flags is a bitmask
+               with the following bits defined:
+
+#define NBPF_SLAVE_RQ_HIGH     1
+#define NBPF_SLAVE_RQ_LOW      2
+#define NBPF_SLAVE_RQ_LEVEL    4
+
+Optional properties:
+- max-burst-mem-read:  limit burst size for memory reads
+  (DMA_MEM_TO_MEM/DMA_MEM_TO_DEV) to this value, specified in bytes, rather
+  than using the maximum burst size allowed by the hardware's buffer size.
+- max-burst-mem-write: limit burst size for memory writes
+  (DMA_DEV_TO_MEM/DMA_MEM_TO_MEM) to this value, specified in bytes, rather
+  than using the maximum burst size allowed by the hardware's buffer size.
+  If both max-burst-mem-read and max-burst-mem-write are set, DMA_MEM_TO_MEM
+  will use the lower value.
+
+You can use dma-channels and dma-requests as described in dma.txt, although they
+won't be used, this information is derived from the compatibility string.
+
+Example:
+
+       dma: dma-controller@48000000 {
+               compatible = "renesas,nbpfaxi64dmac8b4";
+               reg = <0x48000000 0x400>;
+               interrupts = <0 12 0x4
+                             0 13 0x4
+                             0 14 0x4
+                             0 15 0x4
+                             0 16 0x4
+                             0 17 0x4
+                             0 18 0x4
+                             0 19 0x4>;
+               #dma-cells = <2>;
+               dma-channels = <8>;
+               dma-requests = <8>;
+       };
+
+* DMA client
+
+Required properties:
+
+dmas and dma-names are required, as described in dma.txt.
+
+Example:
+
+#include <dt-bindings/dma/nbpfaxi.h>
+
+...
+               dmas = <&dma 0 (NBPF_SLAVE_RQ_HIGH | NBPF_SLAVE_RQ_LEVEL)
+                       &dma 1 (NBPF_SLAVE_RQ_HIGH | NBPF_SLAVE_RQ_LEVEL)>;
+               dma-names = "rx", "tx";
diff --git a/Documentation/devicetree/bindings/dma/renesas,shdma.txt b/Documentation/devicetree/bindings/dma/renesas,shdma.txt
new file mode 100644 (file)
index 0000000..a91920a
--- /dev/null
@@ -0,0 +1,84 @@
+* SHDMA Device Tree bindings
+
+Sh-/r-mobile and R-Car systems often have multiple identical DMA controller
+instances, capable of serving any of a common set of DMA slave devices, using
+the same configuration. To describe this topology we require all compatible
+SHDMA DT nodes to be placed under a DMA multiplexer node. All such compatible
+DMAC instances have the same number of channels and use the same DMA
+descriptors. Therefore respective DMA DT bindings can also all be placed in the
+multiplexer node. Even if there is only one such DMAC instance on a system, it
+still has to be placed under such a multiplexer node.
+
+* DMA multiplexer
+
+Required properties:
+- compatible:  should be "renesas,shdma-mux"
+- #dma-cells:  should be <1>, see "dmas" property below
+
+Optional properties (currently unused):
+- dma-channels:        number of DMA channels
+- dma-requests:        number of DMA request signals
+
+* DMA controller
+
+Required properties:
+- compatible:  should be of the form "renesas,shdma-<soc>", where <soc> should
+               be replaced with the desired SoC model, e.g.
+               "renesas,shdma-r8a73a4" for the system DMAC on r8a73a4 SoC
+
+Example:
+       dmac: dma-multiplexer@0 {
+               compatible = "renesas,shdma-mux";
+               #dma-cells = <1>;
+               dma-channels = <20>;
+               dma-requests = <256>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               dma0: dma-controller@e6700020 {
+                       compatible = "renesas,shdma-r8a73a4";
+                       reg = <0 0xe6700020 0 0x89e0>;
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 220 4
+                                       0 200 4
+                                       0 201 4
+                                       0 202 4
+                                       0 203 4
+                                       0 204 4
+                                       0 205 4
+                                       0 206 4
+                                       0 207 4
+                                       0 208 4
+                                       0 209 4
+                                       0 210 4
+                                       0 211 4
+                                       0 212 4
+                                       0 213 4
+                                       0 214 4
+                                       0 215 4
+                                       0 216 4
+                                       0 217 4
+                                       0 218 4
+                                       0 219 4>;
+                       interrupt-names = "error",
+                                       "ch0", "ch1", "ch2", "ch3",
+                                       "ch4", "ch5", "ch6", "ch7",
+                                       "ch8", "ch9", "ch10", "ch11",
+                                       "ch12", "ch13", "ch14", "ch15",
+                                       "ch16", "ch17", "ch18", "ch19";
+               };
+       };
+
+* DMA client
+
+Required properties:
+- dmas:                a list of <[DMA multiplexer phandle] [MID/RID value]> pairs,
+               where MID/RID values are fixed handles, specified in the SoC
+               manual
+- dma-names:   a list of DMA channel names, one per "dmas" entry
+
+Example:
+       dmas = <&dmac 0xd1
+               &dmac 0xd2>;
+       dma-names = "tx", "rx";
diff --git a/Documentation/devicetree/bindings/dma/shdma.txt b/Documentation/devicetree/bindings/dma/shdma.txt
deleted file mode 100644 (file)
index a91920a..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-* SHDMA Device Tree bindings
-
-Sh-/r-mobile and R-Car systems often have multiple identical DMA controller
-instances, capable of serving any of a common set of DMA slave devices, using
-the same configuration. To describe this topology we require all compatible
-SHDMA DT nodes to be placed under a DMA multiplexer node. All such compatible
-DMAC instances have the same number of channels and use the same DMA
-descriptors. Therefore respective DMA DT bindings can also all be placed in the
-multiplexer node. Even if there is only one such DMAC instance on a system, it
-still has to be placed under such a multiplexer node.
-
-* DMA multiplexer
-
-Required properties:
-- compatible:  should be "renesas,shdma-mux"
-- #dma-cells:  should be <1>, see "dmas" property below
-
-Optional properties (currently unused):
-- dma-channels:        number of DMA channels
-- dma-requests:        number of DMA request signals
-
-* DMA controller
-
-Required properties:
-- compatible:  should be of the form "renesas,shdma-<soc>", where <soc> should
-               be replaced with the desired SoC model, e.g.
-               "renesas,shdma-r8a73a4" for the system DMAC on r8a73a4 SoC
-
-Example:
-       dmac: dma-multiplexer@0 {
-               compatible = "renesas,shdma-mux";
-               #dma-cells = <1>;
-               dma-channels = <20>;
-               dma-requests = <256>;
-               #address-cells = <2>;
-               #size-cells = <2>;
-               ranges;
-
-               dma0: dma-controller@e6700020 {
-                       compatible = "renesas,shdma-r8a73a4";
-                       reg = <0 0xe6700020 0 0x89e0>;
-                       interrupt-parent = <&gic>;
-                       interrupts = <0 220 4
-                                       0 200 4
-                                       0 201 4
-                                       0 202 4
-                                       0 203 4
-                                       0 204 4
-                                       0 205 4
-                                       0 206 4
-                                       0 207 4
-                                       0 208 4
-                                       0 209 4
-                                       0 210 4
-                                       0 211 4
-                                       0 212 4
-                                       0 213 4
-                                       0 214 4
-                                       0 215 4
-                                       0 216 4
-                                       0 217 4
-                                       0 218 4
-                                       0 219 4>;
-                       interrupt-names = "error",
-                                       "ch0", "ch1", "ch2", "ch3",
-                                       "ch4", "ch5", "ch6", "ch7",
-                                       "ch8", "ch9", "ch10", "ch11",
-                                       "ch12", "ch13", "ch14", "ch15",
-                                       "ch16", "ch17", "ch18", "ch19";
-               };
-       };
-
-* DMA client
-
-Required properties:
-- dmas:                a list of <[DMA multiplexer phandle] [MID/RID value]> pairs,
-               where MID/RID values are fixed handles, specified in the SoC
-               manual
-- dma-names:   a list of DMA channel names, one per "dmas" entry
-
-Example:
-       dmas = <&dmac 0xd1
-               &dmac 0xd2>;
-       dma-names = "tx", "rx";
diff --git a/Documentation/devicetree/bindings/dma/sun4i-dma.txt b/Documentation/devicetree/bindings/dma/sun4i-dma.txt
deleted file mode 100644 (file)
index 8ad556a..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-Allwinner A10 DMA Controller
-
-This driver follows the generic DMA bindings defined in dma.txt.
-
-Required properties:
-
-- compatible:  Must be "allwinner,sun4i-a10-dma"
-- reg:         Should contain the registers base address and length
-- interrupts:  Should contain a reference to the interrupt used by this device
-- clocks:      Should contain a reference to the parent AHB clock
-- #dma-cells : Should be 2, first cell denoting normal or dedicated dma,
-               second cell holding the request line number.
-
-Example:
-       dma: dma-controller@1c02000 {
-               compatible = "allwinner,sun4i-a10-dma";
-               reg = <0x01c02000 0x1000>;
-               interrupts = <27>;
-               clocks = <&ahb_gates 6>;
-               #dma-cells = <2>;
-       };
-
-Clients:
-
-DMA clients connected to the Allwinner A10 DMA controller must use the
-format described in the dma.txt file, using a three-cell specifier for
-each channel: a phandle plus two integer cells.
-The three cells in order are:
-
-1. A phandle pointing to the DMA controller.
-2. Whether it is using normal (0) or dedicated (1) channels
-3. The port ID as specified in the datasheet
-
-Example:
-       spi2: spi@1c17000 {
-               compatible = "allwinner,sun4i-a10-spi";
-               reg = <0x01c17000 0x1000>;
-               interrupts = <0 12 4>;
-               clocks = <&ahb_gates 22>, <&spi2_clk>;
-               clock-names = "ahb", "mod";
-               dmas = <&dma 1 29>, <&dma 1 28>;
-               dma-names = "rx", "tx";
-               #address-cells = <1>;
-               #size-cells = <0>;
-       };
diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
deleted file mode 100644 (file)
index cae31f4..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-Allwinner A31 DMA Controller
-
-This driver follows the generic DMA bindings defined in dma.txt.
-
-Required properties:
-
-- compatible:  Must be one of
-                 "allwinner,sun6i-a31-dma"
-                 "allwinner,sun8i-a23-dma"
-                 "allwinner,sun8i-a83t-dma"
-                 "allwinner,sun8i-h3-dma"
-                 "allwinner,sun8i-v3s-dma"
-- reg:         Should contain the registers base address and length
-- interrupts:  Should contain a reference to the interrupt used by this device
-- clocks:      Should contain a reference to the parent AHB clock
-- resets:      Should contain a reference to the reset controller asserting
-               this device in reset
-- #dma-cells : Should be 1, a single cell holding a line request number
-
-Example:
-       dma: dma-controller@1c02000 {
-               compatible = "allwinner,sun6i-a31-dma";
-               reg = <0x01c02000 0x1000>;
-               interrupts = <0 50 4>;
-               clocks = <&ahb1_gates 6>;
-               resets = <&ahb1_rst 6>;
-               #dma-cells = <1>;
-       };
-
-------------------------------------------------------------------------------
-For A64 and H6 DMA controller:
-
-Required properties:
-- compatible:  Must be one of
-                 "allwinner,sun50i-a64-dma"
-                 "allwinner,sun50i-h6-dma"
-- dma-channels: Number of DMA channels supported by the controller.
-               Refer to Documentation/devicetree/bindings/dma/dma.txt
-- clocks:      In addition to parent AHB clock, it should also contain mbus
-               clock (H6 only)
-- clock-names: Should contain "bus" and "mbus" (H6 only)
-- all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells
-
-Optional properties:
-- dma-requests: Number of DMA request signals supported by the controller.
-               Refer to Documentation/devicetree/bindings/dma/dma.txt
-
-Example:
-       dma: dma-controller@1c02000 {
-               compatible = "allwinner,sun50i-a64-dma";
-               reg = <0x01c02000 0x1000>;
-               interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&ccu CLK_BUS_DMA>;
-               dma-channels = <8>;
-               dma-requests = <27>;
-               resets = <&ccu RST_BUS_DMA>;
-               #dma-cells = <1>;
-       };
-------------------------------------------------------------------------------
-
-Clients:
-
-DMA clients connected to the A31 DMA controller must use the format
-described in the dma.txt file, using a two-cell specifier for each
-channel: a phandle plus one integer cells.
-The two cells in order are:
-
-1. A phandle pointing to the DMA controller.
-2. The port ID as specified in the datasheet
-
-Example:
-spi2: spi@1c6a000 {
-       compatible = "allwinner,sun6i-a31-spi";
-       reg = <0x01c6a000 0x1000>;
-       interrupts = <0 67 4>;
-       clocks = <&ahb1_gates 22>, <&spi2_clk>;
-       clock-names = "ahb", "mod";
-       dmas = <&dma 25>, <&dma 25>;
-       dma-names = "rx", "tx";
-       resets = <&ahb1_rst 22>;
-};
index 698f886b73df343f02fce01e98a87d2194f5b606..7e9a7125607987c0466e9768f46c9a34bb98dbd1 100644 (file)
@@ -15532,7 +15532,7 @@ F:      Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
 SYNOPSYS DESIGNWARE AXI DMAC DRIVER
 M:     Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
 S:     Maintained
-F:     drivers/dma/dwi-axi-dmac/
+F:     drivers/dma/dw-axi-dmac/
 F:     Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.txt
 
 SYNOPSYS DESIGNWARE DMAC DRIVER
index 413efef5fbb6010097d9765e247f99accf192682..7c511e3db4c8e7cff0d89128f2e509eda114a536 100644 (file)
@@ -295,7 +295,7 @@ config INTEL_IOATDMA
 
 config INTEL_IOP_ADMA
        tristate "Intel IOP32x ADMA support"
-       depends on ARCH_IOP32X
+       depends on ARCH_IOP32X || COMPILE_TEST
        select DMA_ENGINE
        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
        help
index 30243f5c07105026f90f27eb7bf3bbcb4bfb831b..8a05db3343d39047baf0b9d6ab46e43a1fe4abf1 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -82,6 +83,12 @@ static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
        if (si->base_request_line == 0 && si->num_handshake_signals == 0)
                return 0;
 
+       /* Set up DMA mask based on value from CSRT */
+       ret = dma_coerce_mask_and_coherent(&adev->dev,
+                                          DMA_BIT_MASK(si->dma_address_width));
+       if (ret)
+               return 0;
+
        adma->base_request_line = si->base_request_line;
        adma->end_request_line = si->base_request_line +
                                 si->num_handshake_signals - 1;
@@ -140,7 +147,7 @@ static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma)
  * @dev:               struct device of DMA controller
  * @acpi_dma_xlate:    translation function which converts a dma specifier
  *                     into a dma_chan structure
- * @data               pointer to controller specific data to be used by
+ * @data:              pointer to controller specific data to be used by
  *                     translation function
  *
  * Allocated memory should be freed with appropriate acpi_dma_controller_free()
@@ -224,7 +231,7 @@ static void devm_acpi_dma_release(struct device *dev, void *res)
  * devm_acpi_dma_controller_register - resource managed acpi_dma_controller_register()
  * @dev:               device that is registering this DMA controller
  * @acpi_dma_xlate:    translation function
- * @data               pointer to controller specific data
+ * @data:              pointer to controller specific data
  *
  * Managed acpi_dma_controller_register(). DMA controller registered by this
  * function are automatically freed on driver detach. See
@@ -257,6 +264,7 @@ EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_register);
 
 /**
  * devm_acpi_dma_controller_free - resource managed acpi_dma_controller_free()
+ * @dev:       device that is unregistering as DMA controller
  *
  * Unregister a DMA controller registered with
  * devm_acpi_dma_controller_register(). Normally this function will not need to
index 67100e4e1083b49f07285d7ca2d1ea48f6a8b19f..e4c593f48575c22b6a22c1d14cb05aa03fe675c8 100644 (file)
@@ -896,8 +896,10 @@ static int bcm2835_dma_probe(struct platform_device *pdev)
                pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
 
        rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
-       if (rc)
+       if (rc) {
+               dev_err(&pdev->dev, "Unable to set DMA mask\n");
                return rc;
+       }
 
        od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
        if (!od)
index 7fe9309a876bde8fcb6e035dd0fd27baf464f333..cafb1cc065bb76f397541f54bb597982dbc4ece4 100644 (file)
@@ -92,6 +92,7 @@
 #define JZ_SOC_DATA_PROGRAMMABLE_DMA   BIT(1)
 #define JZ_SOC_DATA_PER_CHAN_PM                BIT(2)
 #define JZ_SOC_DATA_NO_DCKES_DCKEC     BIT(3)
+#define JZ_SOC_DATA_BREAK_LINKS                BIT(4)
 
 /**
  * struct jz4780_dma_hwdesc - descriptor structure read by the DMA controller.
@@ -355,6 +356,7 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg(
        void *context)
 {
        struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
+       struct jz4780_dma_dev *jzdma = jz4780_dma_chan_parent(jzchan);
        struct jz4780_dma_desc *desc;
        unsigned int i;
        int err;
@@ -375,7 +377,8 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg(
 
                desc->desc[i].dcm |= JZ_DMA_DCM_TIE;
 
-               if (i != (sg_len - 1)) {
+               if (i != (sg_len - 1) &&
+                   !(jzdma->soc_data->flags & JZ_SOC_DATA_BREAK_LINKS)) {
                        /* Automatically proceeed to the next descriptor. */
                        desc->desc[i].dcm |= JZ_DMA_DCM_LINK;
 
@@ -664,6 +667,8 @@ static enum dma_status jz4780_dma_tx_status(struct dma_chan *chan,
 static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma,
                                struct jz4780_dma_chan *jzchan)
 {
+       const unsigned int soc_flags = jzdma->soc_data->flags;
+       struct jz4780_dma_desc *desc = jzchan->desc;
        uint32_t dcs;
        bool ack = true;
 
@@ -691,8 +696,11 @@ static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma,
 
                                jz4780_dma_begin(jzchan);
                        } else if (dcs & JZ_DMA_DCS_TT) {
-                               vchan_cookie_complete(&jzchan->desc->vdesc);
-                               jzchan->desc = NULL;
+                               if (!(soc_flags & JZ_SOC_DATA_BREAK_LINKS) ||
+                                   (jzchan->curr_hwdesc + 1 == desc->count)) {
+                                       vchan_cookie_complete(&desc->vdesc);
+                                       jzchan->desc = NULL;
+                               }
 
                                jz4780_dma_begin(jzchan);
                        } else {
@@ -878,10 +886,8 @@ static int jz4780_dma_probe(struct platform_device *pdev)
        }
 
        ret = platform_get_irq(pdev, 0);
-       if (ret < 0) {
-               dev_err(dev, "failed to get IRQ: %d\n", ret);
+       if (ret < 0)
                return ret;
-       }
 
        jzdma->irq = ret;
 
@@ -992,6 +998,7 @@ static int jz4780_dma_remove(struct platform_device *pdev)
 static const struct jz4780_dma_soc_data jz4740_dma_soc_data = {
        .nb_channels = 6,
        .transfer_ord_max = 5,
+       .flags = JZ_SOC_DATA_BREAK_LINKS,
 };
 
 static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = {
index 3d22ae8dca7203ab797646ed6e972aedeb84a32b..a2cadfa2e6d7848e8d4a163a0a6e5f387b26622c 100644 (file)
@@ -72,6 +72,10 @@ static bool norandom;
 module_param(norandom, bool, 0644);
 MODULE_PARM_DESC(norandom, "Disable random offset setup (default: random)");
 
+static bool polled;
+module_param(polled, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
+
 static bool verbose;
 module_param(verbose, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)");
@@ -110,6 +114,7 @@ struct dmatest_params {
        bool            norandom;
        int             alignment;
        unsigned int    transfer_size;
+       bool            polled;
 };
 
 /**
@@ -651,7 +656,10 @@ static int dmatest_func(void *data)
        /*
         * src and dst buffers are freed by ourselves below
         */
-       flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+       if (params->polled)
+               flags = DMA_CTRL_ACK;
+       else
+               flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
 
        ktime = ktime_get();
        while (!kthread_should_stop()
@@ -780,8 +788,10 @@ static int dmatest_func(void *data)
                }
 
                done->done = false;
-               tx->callback = dmatest_callback;
-               tx->callback_param = done;
+               if (!params->polled) {
+                       tx->callback = dmatest_callback;
+                       tx->callback_param = done;
+               }
                cookie = tx->tx_submit(tx);
 
                if (dma_submit_error(cookie)) {
@@ -790,12 +800,22 @@ static int dmatest_func(void *data)
                        msleep(100);
                        goto error_unmap_continue;
                }
-               dma_async_issue_pending(chan);
 
-               wait_event_freezable_timeout(thread->done_wait, done->done,
-                                            msecs_to_jiffies(params->timeout));
+               if (params->polled) {
+                       status = dma_sync_wait(chan, cookie);
+                       dmaengine_terminate_sync(chan);
+                       if (status == DMA_COMPLETE)
+                               done->done = true;
+               } else {
+                       dma_async_issue_pending(chan);
+
+                       wait_event_freezable_timeout(thread->done_wait,
+                                       done->done,
+                                       msecs_to_jiffies(params->timeout));
 
-               status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
+                       status = dma_async_is_tx_complete(chan, cookie, NULL,
+                                                         NULL);
+               }
 
                if (!done->done) {
                        result("test timed out", total_tests, src->off, dst->off,
@@ -1065,6 +1085,7 @@ static void add_threaded_test(struct dmatest_info *info)
        params->norandom = norandom;
        params->alignment = alignment;
        params->transfer_size = transfer_size;
+       params->polled = polled;
 
        request_channels(info, DMA_MEMCPY);
        request_channels(info, DMA_MEMSET);
index 63ed895c09aaf3681799213c6de49cfe45b8dcc3..b6f06699e91a9d6a8159d407dc1861ac59b50424 100644 (file)
@@ -3,7 +3,9 @@ obj-$(CONFIG_DW_DMAC_CORE)      += dw_dmac_core.o
 dw_dmac_core-objs      := core.o dw.o idma32.o
 
 obj-$(CONFIG_DW_DMAC)          += dw_dmac.o
-dw_dmac-objs           := platform.o
+dw_dmac-y                      := platform.o
+dw_dmac-$(CONFIG_ACPI)         += acpi.o
+dw_dmac-$(CONFIG_OF)           += of.o
 
 obj-$(CONFIG_DW_DMAC_PCI)      += dw_dmac_pci.o
 dw_dmac_pci-objs       := pci.o
diff --git a/drivers/dma/dw/acpi.c b/drivers/dma/dw/acpi.c
new file mode 100644 (file)
index 0000000..f6e8d55
--- /dev/null
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2013,2019 Intel Corporation
+
+#include <linux/acpi.h>
+#include <linux/acpi_dma.h>
+
+#include "internal.h"
+
+static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param)
+{
+       struct acpi_dma_spec *dma_spec = param;
+       struct dw_dma_slave slave = {
+               .dma_dev = dma_spec->dev,
+               .src_id = dma_spec->slave_id,
+               .dst_id = dma_spec->slave_id,
+               .m_master = 0,
+               .p_master = 1,
+       };
+
+       return dw_dma_filter(chan, &slave);
+}
+
+void dw_dma_acpi_controller_register(struct dw_dma *dw)
+{
+       struct device *dev = dw->dma.dev;
+       struct acpi_dma_filter_info *info;
+       int ret;
+
+       if (!has_acpi_companion(dev))
+               return;
+
+       info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return;
+
+       dma_cap_zero(info->dma_cap);
+       dma_cap_set(DMA_SLAVE, info->dma_cap);
+       info->filter_fn = dw_dma_acpi_filter;
+
+       ret = acpi_dma_controller_register(dev, acpi_dma_simple_xlate, info);
+       if (ret)
+               dev_err(dev, "could not register acpi_dma_controller\n");
+}
+
+void dw_dma_acpi_controller_free(struct dw_dma *dw)
+{
+       struct device *dev = dw->dma.dev;
+
+       if (!has_acpi_companion(dev))
+               return;
+
+       acpi_dma_controller_free(dev);
+}
index 1dd7a4e6dd235b871ae9d3c105d85d5fd585af4d..2e1c52eefdeb44d4cac97f75d6418cd437d777c9 100644 (file)
@@ -23,4 +23,55 @@ int do_dw_dma_enable(struct dw_dma_chip *chip);
 
 extern bool dw_dma_filter(struct dma_chan *chan, void *param);
 
+#ifdef CONFIG_ACPI
+void dw_dma_acpi_controller_register(struct dw_dma *dw);
+void dw_dma_acpi_controller_free(struct dw_dma *dw);
+#else /* !CONFIG_ACPI */
+static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {}
+static inline void dw_dma_acpi_controller_free(struct dw_dma *dw) {}
+#endif /* !CONFIG_ACPI */
+
+struct platform_device;
+
+#ifdef CONFIG_OF
+struct dw_dma_platform_data *dw_dma_parse_dt(struct platform_device *pdev);
+void dw_dma_of_controller_register(struct dw_dma *dw);
+void dw_dma_of_controller_free(struct dw_dma *dw);
+#else
+static inline struct dw_dma_platform_data *dw_dma_parse_dt(struct platform_device *pdev)
+{
+       return NULL;
+}
+static inline void dw_dma_of_controller_register(struct dw_dma *dw) {}
+static inline void dw_dma_of_controller_free(struct dw_dma *dw) {}
+#endif
+
+struct dw_dma_chip_pdata {
+       const struct dw_dma_platform_data *pdata;
+       int (*probe)(struct dw_dma_chip *chip);
+       int (*remove)(struct dw_dma_chip *chip);
+       struct dw_dma_chip *chip;
+};
+
+static __maybe_unused const struct dw_dma_chip_pdata dw_dma_chip_pdata = {
+       .probe = dw_dma_probe,
+       .remove = dw_dma_remove,
+};
+
+static const struct dw_dma_platform_data idma32_pdata = {
+       .nr_channels = 8,
+       .chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
+       .chan_priority = CHAN_PRIORITY_ASCENDING,
+       .block_size = 131071,
+       .nr_masters = 1,
+       .data_width = {4},
+       .multi_block = {1, 1, 1, 1, 1, 1, 1, 1},
+};
+
+static __maybe_unused const struct dw_dma_chip_pdata idma32_chip_pdata = {
+       .pdata = &idma32_pdata,
+       .probe = idma32_dma_probe,
+       .remove = idma32_dma_remove,
+};
+
 #endif /* _DMA_DW_INTERNAL_H */
diff --git a/drivers/dma/dw/of.c b/drivers/dma/dw/of.c
new file mode 100644 (file)
index 0000000..9e27831
--- /dev/null
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Platform driver for the Synopsys DesignWare DMA Controller
+ *
+ * Copyright (C) 2007-2008 Atmel Corporation
+ * Copyright (C) 2010-2011 ST Microelectronics
+ * Copyright (C) 2013 Intel Corporation
+ */
+
+#include <linux/of.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+
+#include "internal.h"
+
+static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec,
+                                       struct of_dma *ofdma)
+{
+       struct dw_dma *dw = ofdma->of_dma_data;
+       struct dw_dma_slave slave = {
+               .dma_dev = dw->dma.dev,
+       };
+       dma_cap_mask_t cap;
+
+       if (dma_spec->args_count != 3)
+               return NULL;
+
+       slave.src_id = dma_spec->args[0];
+       slave.dst_id = dma_spec->args[0];
+       slave.m_master = dma_spec->args[1];
+       slave.p_master = dma_spec->args[2];
+
+       if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS ||
+                   slave.dst_id >= DW_DMA_MAX_NR_REQUESTS ||
+                   slave.m_master >= dw->pdata->nr_masters ||
+                   slave.p_master >= dw->pdata->nr_masters))
+               return NULL;
+
+       dma_cap_zero(cap);
+       dma_cap_set(DMA_SLAVE, cap);
+
+       /* TODO: there should be a simpler way to do this */
+       return dma_request_channel(cap, dw_dma_filter, &slave);
+}
+
+struct dw_dma_platform_data *dw_dma_parse_dt(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct dw_dma_platform_data *pdata;
+       u32 tmp, arr[DW_DMA_MAX_NR_MASTERS], mb[DW_DMA_MAX_NR_CHANNELS];
+       u32 nr_masters;
+       u32 nr_channels;
+
+       if (!np) {
+               dev_err(&pdev->dev, "Missing DT data\n");
+               return NULL;
+       }
+
+       if (of_property_read_u32(np, "dma-masters", &nr_masters))
+               return NULL;
+       if (nr_masters < 1 || nr_masters > DW_DMA_MAX_NR_MASTERS)
+               return NULL;
+
+       if (of_property_read_u32(np, "dma-channels", &nr_channels))
+               return NULL;
+       if (nr_channels > DW_DMA_MAX_NR_CHANNELS)
+               return NULL;
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       pdata->nr_masters = nr_masters;
+       pdata->nr_channels = nr_channels;
+
+       if (!of_property_read_u32(np, "chan_allocation_order", &tmp))
+               pdata->chan_allocation_order = (unsigned char)tmp;
+
+       if (!of_property_read_u32(np, "chan_priority", &tmp))
+               pdata->chan_priority = tmp;
+
+       if (!of_property_read_u32(np, "block_size", &tmp))
+               pdata->block_size = tmp;
+
+       if (!of_property_read_u32_array(np, "data-width", arr, nr_masters)) {
+               for (tmp = 0; tmp < nr_masters; tmp++)
+                       pdata->data_width[tmp] = arr[tmp];
+       } else if (!of_property_read_u32_array(np, "data_width", arr, nr_masters)) {
+               for (tmp = 0; tmp < nr_masters; tmp++)
+                       pdata->data_width[tmp] = BIT(arr[tmp] & 0x07);
+       }
+
+       if (!of_property_read_u32_array(np, "multi-block", mb, nr_channels)) {
+               for (tmp = 0; tmp < nr_channels; tmp++)
+                       pdata->multi_block[tmp] = mb[tmp];
+       } else {
+               for (tmp = 0; tmp < nr_channels; tmp++)
+                       pdata->multi_block[tmp] = 1;
+       }
+
+       if (!of_property_read_u32(np, "snps,dma-protection-control", &tmp)) {
+               if (tmp > CHAN_PROTCTL_MASK)
+                       return NULL;
+               pdata->protctl = tmp;
+       }
+
+       return pdata;
+}
+
+void dw_dma_of_controller_register(struct dw_dma *dw)
+{
+       struct device *dev = dw->dma.dev;
+       int ret;
+
+       if (!dev->of_node)
+               return;
+
+       ret = of_dma_controller_register(dev->of_node, dw_dma_of_xlate, dw);
+       if (ret)
+               dev_err(dev, "could not register of_dma_controller\n");
+}
+
+void dw_dma_of_controller_free(struct dw_dma *dw)
+{
+       struct device *dev = dw->dma.dev;
+
+       if (!dev->of_node)
+               return;
+
+       of_dma_controller_free(dev->of_node);
+}
index 8de87b15a9889e1976171cd0f7342e875d652fb2..cf6e8ec4c0ff47c20e7420ae3c8f4f697bb32370 100644 (file)
 
 #include "internal.h"
 
-struct dw_dma_pci_data {
-       const struct dw_dma_platform_data *pdata;
-       int (*probe)(struct dw_dma_chip *chip);
-       int (*remove)(struct dw_dma_chip *chip);
-       struct dw_dma_chip *chip;
-};
-
-static const struct dw_dma_pci_data dw_pci_data = {
-       .probe = dw_dma_probe,
-       .remove = dw_dma_remove,
-};
-
-static const struct dw_dma_platform_data idma32_pdata = {
-       .nr_channels = 8,
-       .chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
-       .chan_priority = CHAN_PRIORITY_ASCENDING,
-       .block_size = 131071,
-       .nr_masters = 1,
-       .data_width = {4},
-       .multi_block = {1, 1, 1, 1, 1, 1, 1, 1},
-};
-
-static const struct dw_dma_pci_data idma32_pci_data = {
-       .pdata = &idma32_pdata,
-       .probe = idma32_dma_probe,
-       .remove = idma32_dma_remove,
-};
-
 static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
-       const struct dw_dma_pci_data *drv_data = (void *)pid->driver_data;
-       struct dw_dma_pci_data *data;
+       const struct dw_dma_chip_pdata *drv_data = (void *)pid->driver_data;
+       struct dw_dma_chip_pdata *data;
        struct dw_dma_chip *chip;
        int ret;
 
@@ -95,7 +67,7 @@ static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
 
 static void dw_pci_remove(struct pci_dev *pdev)
 {
-       struct dw_dma_pci_data *data = pci_get_drvdata(pdev);
+       struct dw_dma_chip_pdata *data = pci_get_drvdata(pdev);
        struct dw_dma_chip *chip = data->chip;
        int ret;
 
@@ -108,7 +80,7 @@ static void dw_pci_remove(struct pci_dev *pdev)
 
 static int dw_pci_suspend_late(struct device *dev)
 {
-       struct dw_dma_pci_data *data = dev_get_drvdata(dev);
+       struct dw_dma_chip_pdata *data = dev_get_drvdata(dev);
        struct dw_dma_chip *chip = data->chip;
 
        return do_dw_dma_disable(chip);
@@ -116,7 +88,7 @@ static int dw_pci_suspend_late(struct device *dev)
 
 static int dw_pci_resume_early(struct device *dev)
 {
-       struct dw_dma_pci_data *data = dev_get_drvdata(dev);
+       struct dw_dma_chip_pdata *data = dev_get_drvdata(dev);
        struct dw_dma_chip *chip = data->chip;
 
        return do_dw_dma_enable(chip);
@@ -130,29 +102,29 @@ static const struct dev_pm_ops dw_pci_dev_pm_ops = {
 
 static const struct pci_device_id dw_pci_id_table[] = {
        /* Medfield (GPDMA) */
-       { PCI_VDEVICE(INTEL, 0x0827), (kernel_ulong_t)&dw_pci_data },
+       { PCI_VDEVICE(INTEL, 0x0827), (kernel_ulong_t)&dw_dma_chip_pdata },
 
        /* BayTrail */
-       { PCI_VDEVICE(INTEL, 0x0f06), (kernel_ulong_t)&dw_pci_data },
-       { PCI_VDEVICE(INTEL, 0x0f40), (kernel_ulong_t)&dw_pci_data },
+       { PCI_VDEVICE(INTEL, 0x0f06), (kernel_ulong_t)&dw_dma_chip_pdata },
+       { PCI_VDEVICE(INTEL, 0x0f40), (kernel_ulong_t)&dw_dma_chip_pdata },
 
        /* Merrifield */
-       { PCI_VDEVICE(INTEL, 0x11a2), (kernel_ulong_t)&idma32_pci_data },
+       { PCI_VDEVICE(INTEL, 0x11a2), (kernel_ulong_t)&idma32_chip_pdata },
 
        /* Braswell */
-       { PCI_VDEVICE(INTEL, 0x2286), (kernel_ulong_t)&dw_pci_data },
-       { PCI_VDEVICE(INTEL, 0x22c0), (kernel_ulong_t)&dw_pci_data },
+       { PCI_VDEVICE(INTEL, 0x2286), (kernel_ulong_t)&dw_dma_chip_pdata },
+       { PCI_VDEVICE(INTEL, 0x22c0), (kernel_ulong_t)&dw_dma_chip_pdata },
 
-       /* Elkhart Lake iDMA 32-bit (OSE DMA) */
-       { PCI_VDEVICE(INTEL, 0x4bb4), (kernel_ulong_t)&idma32_pci_data },
-       { PCI_VDEVICE(INTEL, 0x4bb5), (kernel_ulong_t)&idma32_pci_data },
-       { PCI_VDEVICE(INTEL, 0x4bb6), (kernel_ulong_t)&idma32_pci_data },
+       /* Elkhart Lake iDMA 32-bit (PSE DMA) */
+       { PCI_VDEVICE(INTEL, 0x4bb4), (kernel_ulong_t)&idma32_chip_pdata },
+       { PCI_VDEVICE(INTEL, 0x4bb5), (kernel_ulong_t)&idma32_chip_pdata },
+       { PCI_VDEVICE(INTEL, 0x4bb6), (kernel_ulong_t)&idma32_chip_pdata },
 
        /* Haswell */
-       { PCI_VDEVICE(INTEL, 0x9c60), (kernel_ulong_t)&dw_pci_data },
+       { PCI_VDEVICE(INTEL, 0x9c60), (kernel_ulong_t)&dw_dma_chip_pdata },
 
        /* Broadwell */
-       { PCI_VDEVICE(INTEL, 0x9ce0), (kernel_ulong_t)&dw_pci_data },
+       { PCI_VDEVICE(INTEL, 0x9ce0), (kernel_ulong_t)&dw_dma_chip_pdata },
 
        { }
 };
index 382dfd9e9600e2753c09e7d82c71f5e936e3c430..c90c798e5ec347f8b2ddf4dbb4a6bd650834d46b 100644 (file)
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/of.h>
-#include <linux/of_dma.h>
 #include <linux/acpi.h>
-#include <linux/acpi_dma.h>
 
 #include "internal.h"
 
 #define DRV_NAME       "dw_dmac"
 
-static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec,
-                                       struct of_dma *ofdma)
-{
-       struct dw_dma *dw = ofdma->of_dma_data;
-       struct dw_dma_slave slave = {
-               .dma_dev = dw->dma.dev,
-       };
-       dma_cap_mask_t cap;
-
-       if (dma_spec->args_count != 3)
-               return NULL;
-
-       slave.src_id = dma_spec->args[0];
-       slave.dst_id = dma_spec->args[0];
-       slave.m_master = dma_spec->args[1];
-       slave.p_master = dma_spec->args[2];
-
-       if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS ||
-                   slave.dst_id >= DW_DMA_MAX_NR_REQUESTS ||
-                   slave.m_master >= dw->pdata->nr_masters ||
-                   slave.p_master >= dw->pdata->nr_masters))
-               return NULL;
-
-       dma_cap_zero(cap);
-       dma_cap_set(DMA_SLAVE, cap);
-
-       /* TODO: there should be a simpler way to do this */
-       return dma_request_channel(cap, dw_dma_filter, &slave);
-}
-
-#ifdef CONFIG_ACPI
-static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param)
-{
-       struct acpi_dma_spec *dma_spec = param;
-       struct dw_dma_slave slave = {
-               .dma_dev = dma_spec->dev,
-               .src_id = dma_spec->slave_id,
-               .dst_id = dma_spec->slave_id,
-               .m_master = 0,
-               .p_master = 1,
-       };
-
-       return dw_dma_filter(chan, &slave);
-}
-
-static void dw_dma_acpi_controller_register(struct dw_dma *dw)
-{
-       struct device *dev = dw->dma.dev;
-       struct acpi_dma_filter_info *info;
-       int ret;
-
-       info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return;
-
-       dma_cap_zero(info->dma_cap);
-       dma_cap_set(DMA_SLAVE, info->dma_cap);
-       info->filter_fn = dw_dma_acpi_filter;
-
-       ret = devm_acpi_dma_controller_register(dev, acpi_dma_simple_xlate,
-                                               info);
-       if (ret)
-               dev_err(dev, "could not register acpi_dma_controller\n");
-}
-#else /* !CONFIG_ACPI */
-static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {}
-#endif /* !CONFIG_ACPI */
-
-#ifdef CONFIG_OF
-static struct dw_dma_platform_data *
-dw_dma_parse_dt(struct platform_device *pdev)
-{
-       struct device_node *np = pdev->dev.of_node;
-       struct dw_dma_platform_data *pdata;
-       u32 tmp, arr[DW_DMA_MAX_NR_MASTERS], mb[DW_DMA_MAX_NR_CHANNELS];
-       u32 nr_masters;
-       u32 nr_channels;
-
-       if (!np) {
-               dev_err(&pdev->dev, "Missing DT data\n");
-               return NULL;
-       }
-
-       if (of_property_read_u32(np, "dma-masters", &nr_masters))
-               return NULL;
-       if (nr_masters < 1 || nr_masters > DW_DMA_MAX_NR_MASTERS)
-               return NULL;
-
-       if (of_property_read_u32(np, "dma-channels", &nr_channels))
-               return NULL;
-       if (nr_channels > DW_DMA_MAX_NR_CHANNELS)
-               return NULL;
-
-       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-       if (!pdata)
-               return NULL;
-
-       pdata->nr_masters = nr_masters;
-       pdata->nr_channels = nr_channels;
-
-       if (!of_property_read_u32(np, "chan_allocation_order", &tmp))
-               pdata->chan_allocation_order = (unsigned char)tmp;
-
-       if (!of_property_read_u32(np, "chan_priority", &tmp))
-               pdata->chan_priority = tmp;
-
-       if (!of_property_read_u32(np, "block_size", &tmp))
-               pdata->block_size = tmp;
-
-       if (!of_property_read_u32_array(np, "data-width", arr, nr_masters)) {
-               for (tmp = 0; tmp < nr_masters; tmp++)
-                       pdata->data_width[tmp] = arr[tmp];
-       } else if (!of_property_read_u32_array(np, "data_width", arr, nr_masters)) {
-               for (tmp = 0; tmp < nr_masters; tmp++)
-                       pdata->data_width[tmp] = BIT(arr[tmp] & 0x07);
-       }
-
-       if (!of_property_read_u32_array(np, "multi-block", mb, nr_channels)) {
-               for (tmp = 0; tmp < nr_channels; tmp++)
-                       pdata->multi_block[tmp] = mb[tmp];
-       } else {
-               for (tmp = 0; tmp < nr_channels; tmp++)
-                       pdata->multi_block[tmp] = 1;
-       }
-
-       if (!of_property_read_u32(np, "snps,dma-protection-control", &tmp)) {
-               if (tmp > CHAN_PROTCTL_MASK)
-                       return NULL;
-               pdata->protctl = tmp;
-       }
-
-       return pdata;
-}
-#else
-static inline struct dw_dma_platform_data *
-dw_dma_parse_dt(struct platform_device *pdev)
-{
-       return NULL;
-}
-#endif
-
 static int dw_probe(struct platform_device *pdev)
 {
+       const struct dw_dma_chip_pdata *match;
+       struct dw_dma_chip_pdata *data;
        struct dw_dma_chip *chip;
        struct device *dev = &pdev->dev;
-       struct resource *mem;
-       const struct dw_dma_platform_data *pdata;
        int err;
 
+       match = device_get_match_data(dev);
+       if (!match)
+               return -ENODEV;
+
+       data = devm_kmemdup(&pdev->dev, match, sizeof(*match), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)
                return -ENOMEM;
@@ -182,8 +47,7 @@ static int dw_probe(struct platform_device *pdev)
        if (chip->irq < 0)
                return chip->irq;
 
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       chip->regs = devm_ioremap_resource(dev, mem);
+       chip->regs = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(chip->regs))
                return PTR_ERR(chip->regs);
 
@@ -191,13 +55,16 @@ static int dw_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       pdata = dev_get_platdata(dev);
-       if (!pdata)
-               pdata = dw_dma_parse_dt(pdev);
+       if (!data->pdata)
+               data->pdata = dev_get_platdata(dev);
+       if (!data->pdata)
+               data->pdata = dw_dma_parse_dt(pdev);
 
        chip->dev = dev;
        chip->id = pdev->id;
-       chip->pdata = pdata;
+       chip->pdata = data->pdata;
+
+       data->chip = chip;
 
        chip->clk = devm_clk_get(chip->dev, "hclk");
        if (IS_ERR(chip->clk))
@@ -208,22 +75,15 @@ static int dw_probe(struct platform_device *pdev)
 
        pm_runtime_enable(&pdev->dev);
 
-       err = dw_dma_probe(chip);
+       err = data->probe(chip);
        if (err)
                goto err_dw_dma_probe;
 
-       platform_set_drvdata(pdev, chip);
+       platform_set_drvdata(pdev, data);
 
-       if (pdev->dev.of_node) {
-               err = of_dma_controller_register(pdev->dev.of_node,
-                                                dw_dma_of_xlate, chip->dw);
-               if (err)
-                       dev_err(&pdev->dev,
-                               "could not register of_dma_controller\n");
-       }
+       dw_dma_of_controller_register(chip->dw);
 
-       if (ACPI_HANDLE(&pdev->dev))
-               dw_dma_acpi_controller_register(chip->dw);
+       dw_dma_acpi_controller_register(chip->dw);
 
        return 0;
 
@@ -235,12 +95,18 @@ err_dw_dma_probe:
 
 static int dw_remove(struct platform_device *pdev)
 {
-       struct dw_dma_chip *chip = platform_get_drvdata(pdev);
+       struct dw_dma_chip_pdata *data = platform_get_drvdata(pdev);
+       struct dw_dma_chip *chip = data->chip;
+       int ret;
+
+       dw_dma_acpi_controller_free(chip->dw);
 
-       if (pdev->dev.of_node)
-               of_dma_controller_free(pdev->dev.of_node);
+       dw_dma_of_controller_free(chip->dw);
+
+       ret = data->remove(chip);
+       if (ret)
+               dev_warn(chip->dev, "can't remove device properly: %d\n", ret);
 
-       dw_dma_remove(chip);
        pm_runtime_disable(&pdev->dev);
        clk_disable_unprepare(chip->clk);
 
@@ -249,7 +115,8 @@ static int dw_remove(struct platform_device *pdev)
 
 static void dw_shutdown(struct platform_device *pdev)
 {
-       struct dw_dma_chip *chip = platform_get_drvdata(pdev);
+       struct dw_dma_chip_pdata *data = platform_get_drvdata(pdev);
+       struct dw_dma_chip *chip = data->chip;
 
        /*
         * We have to call do_dw_dma_disable() to stop any ongoing transfer. On
@@ -269,7 +136,7 @@ static void dw_shutdown(struct platform_device *pdev)
 
 #ifdef CONFIG_OF
 static const struct of_device_id dw_dma_of_id_table[] = {
-       { .compatible = "snps,dma-spear1340" },
+       { .compatible = "snps,dma-spear1340", .data = &dw_dma_chip_pdata },
        {}
 };
 MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
@@ -277,9 +144,15 @@ MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
 
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id dw_dma_acpi_id_table[] = {
-       { "INTL9C60", 0 },
-       { "80862286", 0 },
-       { "808622C0", 0 },
+       { "INTL9C60", (kernel_ulong_t)&dw_dma_chip_pdata },
+       { "80862286", (kernel_ulong_t)&dw_dma_chip_pdata },
+       { "808622C0", (kernel_ulong_t)&dw_dma_chip_pdata },
+
+       /* Elkhart Lake iDMA 32-bit (PSE DMA) */
+       { "80864BB4", (kernel_ulong_t)&idma32_chip_pdata },
+       { "80864BB5", (kernel_ulong_t)&idma32_chip_pdata },
+       { "80864BB6", (kernel_ulong_t)&idma32_chip_pdata },
+
        { }
 };
 MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table);
@@ -289,7 +162,8 @@ MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table);
 
 static int dw_suspend_late(struct device *dev)
 {
-       struct dw_dma_chip *chip = dev_get_drvdata(dev);
+       struct dw_dma_chip_pdata *data = dev_get_drvdata(dev);
+       struct dw_dma_chip *chip = data->chip;
 
        do_dw_dma_disable(chip);
        clk_disable_unprepare(chip->clk);
@@ -299,7 +173,8 @@ static int dw_suspend_late(struct device *dev)
 
 static int dw_resume_early(struct device *dev)
 {
-       struct dw_dma_chip *chip = dev_get_drvdata(dev);
+       struct dw_dma_chip_pdata *data = dev_get_drvdata(dev);
+       struct dw_dma_chip *chip = data->chip;
        int ret;
 
        ret = clk_prepare_enable(chip->clk);
index 44d92c34dec31d4850566ca8d1809e623164e785..b1a7ca91701a80365e74e2f0d6669b8816297629 100644 (file)
@@ -90,8 +90,21 @@ static void mux_configure8(struct fsl_edma_chan *fsl_chan, void __iomem *addr,
        iowrite8(val8, addr + off);
 }
 
+static void mux_configure32(struct fsl_edma_chan *fsl_chan, void __iomem *addr,
+                           u32 off, u32 slot, bool enable)
+{
+       u32 val;
+
+       if (enable)
+               val = EDMAMUX_CHCFG_ENBL << 24 | slot;
+       else
+               val = EDMAMUX_CHCFG_DIS;
+
+       iowrite32(val, addr + off * 4);
+}
+
 void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
-                       unsigned int slot, bool enable)
+                      unsigned int slot, bool enable)
 {
        u32 ch = fsl_chan->vchan.chan.chan_id;
        void __iomem *muxaddr;
@@ -103,7 +116,10 @@ void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
        muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux];
        slot = EDMAMUX_CHCFG_SOURCE(slot);
 
-       mux_configure8(fsl_chan, muxaddr, ch_off, slot, enable);
+       if (fsl_chan->edma->drvdata->version == v3)
+               mux_configure32(fsl_chan, muxaddr, ch_off, slot, enable);
+       else
+               mux_configure8(fsl_chan, muxaddr, ch_off, slot, enable);
 }
 EXPORT_SYMBOL_GPL(fsl_edma_chan_mux);
 
index 4e175560292ca26ab3370ae2e88e96a3ca0bcdbb..5eaa2902ed3919e370f6c77cb401b2ca21f5781f 100644 (file)
@@ -125,6 +125,7 @@ struct fsl_edma_chan {
        dma_addr_t                      dma_dev_addr;
        u32                             dma_dev_size;
        enum dma_data_direction         dma_dir;
+       char                            chan_name[16];
 };
 
 struct fsl_edma_desc {
@@ -139,11 +140,13 @@ struct fsl_edma_desc {
 enum edma_version {
        v1, /* 32ch, Vybrid, mpc57x, etc */
        v2, /* 64ch Coldfire */
+       v3, /* 32ch, i.mx7ulp */
 };
 
 struct fsl_edma_drvdata {
        enum edma_version       version;
        u32                     dmamuxs;
+       bool                    has_dmaclk;
        int                     (*setup_irq)(struct platform_device *pdev,
                                             struct fsl_edma_engine *fsl_edma);
 };
@@ -153,6 +156,7 @@ struct fsl_edma_engine {
        void __iomem            *membase;
        void __iomem            *muxbase[DMAMUX_NR];
        struct clk              *muxclk[DMAMUX_NR];
+       struct clk              *dmaclk;
        struct mutex            fsl_edma_mutex;
        const struct fsl_edma_drvdata *drvdata;
        u32                     n_chans;
index fcbad6ae954a820774f994fbaf1c99d7130df005..b626c06ac2e0bb3d502c5e9625caa9b26e11f9c1 100644 (file)
 
 #include "fsl-edma-common.h"
 
+static void fsl_edma_synchronize(struct dma_chan *chan)
+{
+       struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+
+       vchan_synchronize(&fsl_chan->vchan);
+}
+
 static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id)
 {
        struct fsl_edma_engine *fsl_edma = dev_id;
@@ -125,16 +132,12 @@ fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma
        int ret;
 
        fsl_edma->txirq = platform_get_irq_byname(pdev, "edma-tx");
-       if (fsl_edma->txirq < 0) {
-               dev_err(&pdev->dev, "Can't get edma-tx irq.\n");
+       if (fsl_edma->txirq < 0)
                return fsl_edma->txirq;
-       }
 
        fsl_edma->errirq = platform_get_irq_byname(pdev, "edma-err");
-       if (fsl_edma->errirq < 0) {
-               dev_err(&pdev->dev, "Can't get edma-err irq.\n");
+       if (fsl_edma->errirq < 0)
                return fsl_edma->errirq;
-       }
 
        if (fsl_edma->txirq == fsl_edma->errirq) {
                ret = devm_request_irq(&pdev->dev, fsl_edma->txirq,
@@ -162,6 +165,49 @@ fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma
        return 0;
 }
 
+static int
+fsl_edma2_irq_init(struct platform_device *pdev,
+                  struct fsl_edma_engine *fsl_edma)
+{
+       int i, ret, irq;
+       int count;
+
+       count = platform_irq_count(pdev);
+       dev_dbg(&pdev->dev, "%s Found %d interrupts\r\n", __func__, count);
+       if (count <= 2) {
+               dev_err(&pdev->dev, "Interrupts in DTS not correct.\n");
+               return -EINVAL;
+       }
+       /*
+        * 16 channel independent interrupts + 1 error interrupt on i.mx7ulp.
+        * 2 channel share one interrupt, for example, ch0/ch16, ch1/ch17...
+        * For now, just simply request irq without IRQF_SHARED flag, since 16
+        * channels are enough on i.mx7ulp whose M4 domain own some peripherals.
+        */
+       for (i = 0; i < count; i++) {
+               irq = platform_get_irq(pdev, i);
+               if (irq < 0)
+                       return -ENXIO;
+
+               sprintf(fsl_edma->chans[i].chan_name, "eDMA2-CH%02d", i);
+
+               /* The last IRQ is for eDMA err */
+               if (i == count - 1)
+                       ret = devm_request_irq(&pdev->dev, irq,
+                                               fsl_edma_err_handler,
+                                               0, "eDMA2-ERR", fsl_edma);
+               else
+                       ret = devm_request_irq(&pdev->dev, irq,
+                                               fsl_edma_tx_handler, 0,
+                                               fsl_edma->chans[i].chan_name,
+                                               fsl_edma);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static void fsl_edma_irq_exit(
                struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
 {
@@ -187,8 +233,16 @@ static struct fsl_edma_drvdata vf610_data = {
        .setup_irq = fsl_edma_irq_init,
 };
 
+static struct fsl_edma_drvdata imx7ulp_data = {
+       .version = v3,
+       .dmamuxs = 1,
+       .has_dmaclk = true,
+       .setup_irq = fsl_edma2_irq_init,
+};
+
 static const struct of_device_id fsl_edma_dt_ids[] = {
        { .compatible = "fsl,vf610-edma", .data = &vf610_data},
+       { .compatible = "fsl,imx7ulp-edma", .data = &imx7ulp_data},
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
@@ -236,6 +290,20 @@ static int fsl_edma_probe(struct platform_device *pdev)
        fsl_edma_setup_regs(fsl_edma);
        regs = &fsl_edma->regs;
 
+       if (drvdata->has_dmaclk) {
+               fsl_edma->dmaclk = devm_clk_get(&pdev->dev, "dma");
+               if (IS_ERR(fsl_edma->dmaclk)) {
+                       dev_err(&pdev->dev, "Missing DMA block clock.\n");
+                       return PTR_ERR(fsl_edma->dmaclk);
+               }
+
+               ret = clk_prepare_enable(fsl_edma->dmaclk);
+               if (ret) {
+                       dev_err(&pdev->dev, "DMA clk block failed.\n");
+                       return ret;
+               }
+       }
+
        for (i = 0; i < fsl_edma->drvdata->dmamuxs; i++) {
                char clkname[32];
 
@@ -302,6 +370,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
        fsl_edma->dma_dev.device_pause = fsl_edma_pause;
        fsl_edma->dma_dev.device_resume = fsl_edma_resume;
        fsl_edma->dma_dev.device_terminate_all = fsl_edma_terminate_all;
+       fsl_edma->dma_dev.device_synchronize = fsl_edma_synchronize;
        fsl_edma->dma_dev.device_issue_pending = fsl_edma_issue_pending;
 
        fsl_edma->dma_dev.src_addr_widths = FSL_EDMA_BUSWIDTHS;
index 8e341c0c13bcf5772e7a33eedb9fc6e045c46895..06664fbd2d911638167f35ea06ea57bd0d2565f0 100644 (file)
@@ -758,10 +758,8 @@ fsl_qdma_irq_init(struct platform_device *pdev,
 
        fsl_qdma->error_irq =
                platform_get_irq_byname(pdev, "qdma-error");
-       if (fsl_qdma->error_irq < 0) {
-               dev_err(&pdev->dev, "Can't get qdma controller irq.\n");
+       if (fsl_qdma->error_irq < 0)
                return fsl_qdma->error_irq;
-       }
 
        ret = devm_request_irq(&pdev->dev, fsl_qdma->error_irq,
                               fsl_qdma_error_handler, 0,
@@ -776,11 +774,8 @@ fsl_qdma_irq_init(struct platform_device *pdev,
                fsl_qdma->queue_irq[i] =
                                platform_get_irq_byname(pdev, irq_name);
 
-               if (fsl_qdma->queue_irq[i] < 0) {
-                       dev_err(&pdev->dev,
-                               "Can't get qdma queue %d irq.\n", i);
+               if (fsl_qdma->queue_irq[i] < 0)
                        return fsl_qdma->queue_irq[i];
-               }
 
                ret = devm_request_irq(&pdev->dev,
                                       fsl_qdma->queue_irq[i],
index 00a089e24150ac235877702586e049a48c2e5a2d..5c0fb3134825f56ce02af12738eabcbdbfcbbacf 100644 (file)
@@ -556,6 +556,7 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
                 * We fall-through here intentionally, since a 2D transfer is
                 * similar to MEMCPY just adding the 2D slot configuration.
                 */
+               /* Fall through */
        case IMXDMA_DESC_MEMCPY:
                imx_dmav1_writel(imxdma, d->src, DMA_SAR(imxdmac->channel));
                imx_dmav1_writel(imxdma, d->dest, DMA_DAR(imxdmac->channel));
index a01f4b5d793c4ed591b6666110b7ed00e5bce8e6..9ba74ab7e912e90fe78ab9f02b4120d79ab14fb4 100644 (file)
@@ -1886,10 +1886,6 @@ static int sdma_init(struct sdma_engine *sdma)
        sdma->context_phys = ccb_phys +
                MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control);
 
-       /* Zero-out the CCB structures array just allocated */
-       memset(sdma->channel_control, 0,
-                       MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control));
-
        /* disable all channels */
        for (i = 0; i < sdma->drvdata->num_events; i++)
                writel_relaxed(0, sdma->regs + chnenbl_ofs(sdma, i));
index 70fd8454d0025556689fbe93912f72c7bb57d105..be61c32a876f1196a259eadc4b33544cf9138fb1 100644 (file)
@@ -286,8 +286,7 @@ struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)
                return NULL;
 
        dca = alloc_dca_provider(&ioat_dca_ops,
-                                sizeof(*ioatdca)
-                                     + (sizeof(struct ioat_dca_slot) * slots));
+                                struct_size(ioatdca, req_slots, slots));
        if (!dca)
                return NULL;
 
index 03f4a588cf7faf4ba5c6973b5be0f2f346124152..a3f942a6a946ab7c40196f6152891b62302a5e3a 100644 (file)
@@ -116,9 +116,9 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
        list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
                                        chain_node) {
                pr_debug("\tcookie: %d slot: %d busy: %d "
-                       "this_desc: %#x next_desc: %#llx ack: %d\n",
+                       "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),
+                       &iter->async_tx.phys, (u64)iop_desc_get_next_desc(iter),
                        async_tx_test_ack(&iter->async_tx));
                prefetch(_iter);
                prefetch(&_iter->async_tx);
@@ -364,13 +364,11 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *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;
-       int slots_per_op;
        dma_cookie_t cookie;
        dma_addr_t next_dma;
 
        grp_start = sw_desc->group_head;
        slot_cnt = grp_start->slot_cnt;
-       slots_per_op = grp_start->slots_per_op;
 
        spin_lock_bh(&iop_chan->lock);
        cookie = dma_cookie_assign(tx);
index 546995c2087637c8bfdce527ee9c739332ed9adf..f40051d6aecbcd51bcdf04f560ac130624fea596 100644 (file)
@@ -547,10 +547,8 @@ static int mtk_uart_apdma_probe(struct platform_device *pdev)
                vchan_init(&c->vc, &mtkd->ddev);
 
                rc = platform_get_irq(pdev, i);
-               if (rc < 0) {
-                       dev_err(&pdev->dev, "failed to get IRQ[%d]\n", i);
+               if (rc < 0)
                        goto err_no_dma;
-               }
                c->irq = rc;
        }
 
index fa5dab481203ce36534b905f47f34aec0d443f82..e3850f04f6763fd81527eca39879e14d80cd70eb 100644 (file)
@@ -33,7 +33,6 @@
 #define MV_XOR_V2_DMA_IMSG_CDAT_OFF                    0x014
 #define MV_XOR_V2_DMA_IMSG_THRD_OFF                    0x018
 #define   MV_XOR_V2_DMA_IMSG_THRD_MASK                 0x7FFF
-#define   MV_XOR_V2_DMA_IMSG_THRD_SHIFT                        0x0
 #define   MV_XOR_V2_DMA_IMSG_TIMER_EN                  BIT(18)
 #define MV_XOR_V2_DMA_DESQ_AWATTR_OFF                  0x01C
   /* Same flags as MV_XOR_V2_DMA_DESQ_ARATTR_OFF */
@@ -50,7 +49,6 @@
 #define MV_XOR_V2_DMA_DESQ_ADD_OFF                     0x808
 #define MV_XOR_V2_DMA_IMSG_TMOT                                0x810
 #define   MV_XOR_V2_DMA_IMSG_TIMER_THRD_MASK           0x1FFF
-#define   MV_XOR_V2_DMA_IMSG_TIMER_THRD_SHIFT          0
 
 /* XOR Global registers */
 #define MV_XOR_V2_GLOB_BW_CTRL                         0x4
@@ -261,16 +259,15 @@ void mv_xor_v2_enable_imsg_thrd(struct mv_xor_v2_device *xor_dev)
 
        /* Configure threshold of number of descriptors, and enable timer */
        reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF);
-       reg &= (~MV_XOR_V2_DMA_IMSG_THRD_MASK << MV_XOR_V2_DMA_IMSG_THRD_SHIFT);
-       reg |= (MV_XOR_V2_DONE_IMSG_THRD << MV_XOR_V2_DMA_IMSG_THRD_SHIFT);
+       reg &= ~MV_XOR_V2_DMA_IMSG_THRD_MASK;
+       reg |= MV_XOR_V2_DONE_IMSG_THRD;
        reg |= MV_XOR_V2_DMA_IMSG_TIMER_EN;
        writel(reg, xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF);
 
        /* Configure Timer Threshold */
        reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_TMOT);
-       reg &= (~MV_XOR_V2_DMA_IMSG_TIMER_THRD_MASK <<
-               MV_XOR_V2_DMA_IMSG_TIMER_THRD_SHIFT);
-       reg |= (MV_XOR_V2_TIMER_THRD << MV_XOR_V2_DMA_IMSG_TIMER_THRD_SHIFT);
+       reg &= ~MV_XOR_V2_DMA_IMSG_TIMER_THRD_MASK;
+       reg |= MV_XOR_V2_TIMER_THRD;
        writel(reg, xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_TMOT);
 }
 
index 1163af2ba4a36fef2f313dd09236eee4039236de..6cce9ef61b2944020d67c821606e3451bd2e33bb 100644 (file)
@@ -1922,9 +1922,10 @@ static int dmac_alloc_resources(struct pl330_dmac *pl330)
        if (ret) {
                dev_err(pl330->ddma.dev, "%s:%d Can't to create channels for DMAC!\n",
                        __func__, __LINE__);
-               dma_free_coherent(pl330->ddma.dev,
+               dma_free_attrs(pl330->ddma.dev,
                                chans * pl330->mcbufsz,
-                               pl330->mcode_cpu, pl330->mcode_bus);
+                               pl330->mcode_cpu, pl330->mcode_bus,
+                               DMA_ATTR_PRIVILEGED);
                return ret;
        }
 
@@ -2003,9 +2004,9 @@ static void pl330_del(struct pl330_dmac *pl330)
        /* Free DMAC resources */
        dmac_free_threads(pl330);
 
-       dma_free_coherent(pl330->ddma.dev,
+       dma_free_attrs(pl330->ddma.dev,
                pl330->pcfg.num_chan * pl330->mcbufsz, pl330->mcode_cpu,
-               pl330->mcode_bus);
+               pl330->mcode_bus, DMA_ATTR_PRIVILEGED);
 }
 
 /* forward declaration */
index 5bf8b145c427c890971e30d5fdf334114bdc27a9..bb4471e84e484554231229def9921a967ebc0413 100644 (file)
@@ -749,7 +749,6 @@ struct hidma_lldev *hidma_ll_init(struct device *dev, u32 nr_tres,
        if (!lldev->tre_ring)
                return NULL;
 
-       memset(lldev->tre_ring, 0, (HIDMA_TRE_SIZE + 1) * nr_tres);
        lldev->tre_ring_size = HIDMA_TRE_SIZE * nr_tres;
        lldev->nr_tres = nr_tres;
 
@@ -769,7 +768,6 @@ struct hidma_lldev *hidma_ll_init(struct device *dev, u32 nr_tres,
        if (!lldev->evre_ring)
                return NULL;
 
-       memset(lldev->evre_ring, 0, (HIDMA_EVRE_SIZE + 1) * nr_tres);
        lldev->evre_ring_size = HIDMA_EVRE_SIZE * nr_tres;
 
        /* the EVRE ring has to be EVRE_SIZE aligned */
index 3022d66e7a33bd681b1ee79cf645bc84a5f29b50..806ca02c52d711702793c13804b1fec4ae5ea9ad 100644 (file)
@@ -183,7 +183,6 @@ static int hidma_mgmt_probe(struct platform_device *pdev)
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
-               dev_err(&pdev->dev, "irq resources not found\n");
                rc = irq;
                goto out;
        }
@@ -388,7 +387,6 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
                        ret = PTR_ERR(new_pdev);
                        goto out;
                }
-               of_node_get(child);
                new_pdev->dev.of_node = child;
                of_dma_configure(&new_pdev->dev, child, true);
                /*
@@ -396,9 +394,14 @@ static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
                 * platforms with or without MSI support.
                 */
                of_msi_configure(&new_pdev->dev, child);
-               of_node_put(child);
        }
+
+       kfree(res);
+
+       return ret;
+
 out:
+       of_node_put(child);
        kfree(res);
 
        return ret;
index ad30f3d2c7f693edd49a985d397b5dacb1713aa4..43da8eeb18ef0710b21c43854d2f3a951991d525 100644 (file)
@@ -1237,11 +1237,8 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
                phy->host = s3cdma;
 
                phy->irq = platform_get_irq(pdev, i);
-               if (phy->irq < 0) {
-                       dev_err(&pdev->dev, "failed to get irq %d, err %d\n",
-                               i, phy->irq);
+               if (phy->irq < 0)
                        continue;
-               }
 
                ret = devm_request_irq(&pdev->dev, phy->irq, s3c24xx_dma_irq,
                                       0, pdev->name, phy);
index 1072c450c37ab89d7c78ea0f521927fcb13410ae..3993ab65c62cd34469f755cfdcac52da98f96fef 100644 (file)
@@ -1749,10 +1749,8 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac,
        /* Request the channel interrupt. */
        sprintf(pdev_irqname, "ch%u", index);
        rchan->irq = platform_get_irq_byname(pdev, pdev_irqname);
-       if (rchan->irq < 0) {
-               dev_err(dmac->dev, "no IRQ specified for channel %u\n", index);
+       if (rchan->irq < 0)
                return -ENODEV;
-       }
 
        irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
                                 dev_name(dmac->dev), index);
index 17063aaf51bce98b163e1a61f7430668a3d6e49d..b218a013c2600f449dac819c2ab11ab6ef74ce5e 100644 (file)
@@ -717,10 +717,8 @@ static int usb_dmac_chan_probe(struct usb_dmac *dmac,
        /* Request the channel interrupt. */
        sprintf(pdev_irqname, "ch%u", index);
        uchan->irq = platform_get_irq_byname(pdev, pdev_irqname);
-       if (uchan->irq < 0) {
-               dev_err(dmac->dev, "no IRQ specified for channel %u\n", index);
+       if (uchan->irq < 0)
                return -ENODEV;
-       }
 
        irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
                                 dev_name(dmac->dev), index);
index a3ee0f6bb6640b3b24021e99510750e4af01b896..67087dbe2f9facd8690616304ab7eb1e076c6e8a 100644 (file)
@@ -771,10 +771,8 @@ static int st_fdma_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, fdev);
 
        fdev->irq = platform_get_irq(pdev, 0);
-       if (fdev->irq < 0) {
-               dev_err(&pdev->dev, "Failed to get irq resource\n");
+       if (fdev->irq < 0)
                return -EINVAL;
-       }
 
        ret = devm_request_irq(&pdev->dev, fdev->irq, st_fdma_irq_handler, 0,
                               dev_name(&pdev->dev), fdev);
index ef4d109e718900178f5b7f1bbacd53d5feaa142d..5989b08935211537026f289a0b1eb5bc320b4284 100644 (file)
@@ -243,12 +243,6 @@ static void stm32_dma_write(struct stm32_dma_device *dmadev, u32 reg, u32 val)
        writel_relaxed(val, dmadev->base + reg);
 }
 
-static struct stm32_dma_desc *stm32_dma_alloc_desc(u32 num_sgs)
-{
-       return kzalloc(sizeof(struct stm32_dma_desc) +
-                      sizeof(struct stm32_dma_sg_req) * num_sgs, GFP_NOWAIT);
-}
-
 static int stm32_dma_get_width(struct stm32_dma_chan *chan,
                               enum dma_slave_buswidth width)
 {
@@ -853,7 +847,7 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg(
                return NULL;
        }
 
-       desc = stm32_dma_alloc_desc(sg_len);
+       desc = kzalloc(struct_size(desc, sg_req, sg_len), GFP_NOWAIT);
        if (!desc)
                return NULL;
 
@@ -954,7 +948,7 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic(
 
        num_periods = buf_len / period_len;
 
-       desc = stm32_dma_alloc_desc(num_periods);
+       desc = kzalloc(struct_size(desc, sg_req, num_periods), GFP_NOWAIT);
        if (!desc)
                return NULL;
 
@@ -989,7 +983,7 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
        int i;
 
        num_sgs = DIV_ROUND_UP(len, STM32_DMA_ALIGNED_MAX_DATA_ITEMS);
-       desc = stm32_dma_alloc_desc(num_sgs);
+       desc = kzalloc(struct_size(desc, sg_req, num_sgs), GFP_NOWAIT);
        if (!desc)
                return NULL;
 
@@ -1366,12 +1360,8 @@ static int stm32_dma_probe(struct platform_device *pdev)
        for (i = 0; i < STM32_DMA_MAX_CHANNELS; i++) {
                chan = &dmadev->chan[i];
                ret = platform_get_irq(pdev, i);
-               if (ret < 0)  {
-                       if (ret != -EPROBE_DEFER)
-                               dev_err(&pdev->dev,
-                                       "No irq resource for chan %d\n", i);
+               if (ret < 0)
                        goto err_unregister;
-               }
                chan->irq = ret;
 
                ret = devm_request_irq(&pdev->dev, chan->irq,
index b552949da14b20a3755e540bcc637dcaf661a75e..3c89bd39e09681d47cca617bdcef6cdc1d023afa 100644 (file)
@@ -185,8 +185,7 @@ static int stm32_dmamux_probe(struct platform_device *pdev)
        if (!node)
                return -ENODEV;
 
-       count = device_property_read_u32_array(&pdev->dev, "dma-masters",
-                                              NULL, 0);
+       count = device_property_count_u32(&pdev->dev, "dma-masters");
        if (count < 0) {
                dev_err(&pdev->dev, "Can't get DMA master(s) node\n");
                return -ENODEV;
index 1311de74bfdde5f817937fd2a929a1e02ce00c0f..5838311cf990044f8a0b962590e851ccedc805f1 100644 (file)
@@ -1555,8 +1555,7 @@ static int stm32_mdma_probe(struct platform_device *pdev)
                         nr_requests);
        }
 
-       count = device_property_read_u32_array(&pdev->dev, "st,ahb-addr-masks",
-                                              NULL, 0);
+       count = device_property_count_u32(&pdev->dev, "st,ahb-addr-masks");
        if (count < 0)
                count = 0;
 
@@ -1638,10 +1637,8 @@ static int stm32_mdma_probe(struct platform_device *pdev)
        }
 
        dmadev->irq = platform_get_irq(pdev, 0);
-       if (dmadev->irq < 0) {
-               dev_err(&pdev->dev, "failed to get IRQ\n");
+       if (dmadev->irq < 0)
                return dmadev->irq;
-       }
 
        ret = devm_request_irq(&pdev->dev, dmadev->irq, stm32_mdma_irq_handler,
                               0, dev_name(&pdev->dev), dmadev);
index 1f80568b2613eaeb5f7998a76269292abdca5232..e397a50058c8825f2ea3ac188f8f64d160bf08dc 100644 (file)
@@ -1132,10 +1132,8 @@ static int sun4i_dma_probe(struct platform_device *pdev)
                return PTR_ERR(priv->base);
 
        priv->irq = platform_get_irq(pdev, 0);
-       if (priv->irq < 0) {
-               dev_err(&pdev->dev, "Cannot claim IRQ\n");
+       if (priv->irq < 0)
                return priv->irq;
-       }
 
        priv->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(priv->clk)) {
index ed5b68dcfe50c8bb9c6da0fbca820528d34f93dd..06cd7f867f7cafe2cb11c42c0456fb621edd09af 100644 (file)
@@ -1251,10 +1251,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
                return PTR_ERR(sdc->base);
 
        sdc->irq = platform_get_irq(pdev, 0);
-       if (sdc->irq < 0) {
-               dev_err(&pdev->dev, "Cannot claim IRQ\n");
+       if (sdc->irq < 0)
                return sdc->irq;
-       }
 
        sdc->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(sdc->clk)) {
index 79e9593815f1217eb5d1887ba144c856834f51a6..3a45079d11ecff40db8ea5b1824c55894a7429e7 100644 (file)
@@ -152,6 +152,7 @@ struct tegra_dma_sg_req {
        bool                            last_sg;
        struct list_head                node;
        struct tegra_dma_desc           *dma_desc;
+       unsigned int                    words_xferred;
 };
 
 /*
@@ -496,6 +497,7 @@ static void tegra_dma_configure_for_next(struct tegra_dma_channel *tdc,
        tdc_write(tdc, TEGRA_APBDMA_CHAN_CSR,
                                nsg_req->ch_regs.csr | TEGRA_APBDMA_CSR_ENB);
        nsg_req->configured = true;
+       nsg_req->words_xferred = 0;
 
        tegra_dma_resume(tdc);
 }
@@ -511,6 +513,7 @@ static void tdc_start_head_req(struct tegra_dma_channel *tdc)
                                        typeof(*sg_req), node);
        tegra_dma_start(tdc, sg_req);
        sg_req->configured = true;
+       sg_req->words_xferred = 0;
        tdc->busy = true;
 }
 
@@ -638,6 +641,8 @@ static void handle_cont_sngl_cycle_dma_done(struct tegra_dma_channel *tdc,
                list_add_tail(&dma_desc->cb_node, &tdc->cb_desc);
        dma_desc->cb_count++;
 
+       sgreq->words_xferred = 0;
+
        /* If not last req then put at end of pending list */
        if (!list_is_last(&sgreq->node, &tdc->pending_sg_req)) {
                list_move_tail(&sgreq->node, &tdc->pending_sg_req);
@@ -797,6 +802,65 @@ skip_dma_stop:
        return 0;
 }
 
+static unsigned int tegra_dma_sg_bytes_xferred(struct tegra_dma_channel *tdc,
+                                              struct tegra_dma_sg_req *sg_req)
+{
+       unsigned long status, wcount = 0;
+
+       if (!list_is_first(&sg_req->node, &tdc->pending_sg_req))
+               return 0;
+
+       if (tdc->tdma->chip_data->support_separate_wcount_reg)
+               wcount = tdc_read(tdc, TEGRA_APBDMA_CHAN_WORD_TRANSFER);
+
+       status = tdc_read(tdc, TEGRA_APBDMA_CHAN_STATUS);
+
+       if (!tdc->tdma->chip_data->support_separate_wcount_reg)
+               wcount = status;
+
+       if (status & TEGRA_APBDMA_STATUS_ISE_EOC)
+               return sg_req->req_len;
+
+       wcount = get_current_xferred_count(tdc, sg_req, wcount);
+
+       if (!wcount) {
+               /*
+                * If wcount wasn't ever polled for this SG before, then
+                * simply assume that transfer hasn't started yet.
+                *
+                * Otherwise it's the end of the transfer.
+                *
+                * The alternative would be to poll the status register
+                * until EOC bit is set or wcount goes UP. That's so
+                * because EOC bit is getting set only after the last
+                * burst's completion and counter is less than the actual
+                * transfer size by 4 bytes. The counter value wraps around
+                * in a cyclic mode before EOC is set(!), so we can't easily
+                * distinguish start of transfer from its end.
+                */
+               if (sg_req->words_xferred)
+                       wcount = sg_req->req_len - 4;
+
+       } else if (wcount < sg_req->words_xferred) {
+               /*
+                * This case will never happen for a non-cyclic transfer.
+                *
+                * For a cyclic transfer, although it is possible for the
+                * next transfer to have already started (resetting the word
+                * count), this case should still not happen because we should
+                * have detected that the EOC bit is set and hence the transfer
+                * was completed.
+                */
+               WARN_ON_ONCE(1);
+
+               wcount = sg_req->req_len - 4;
+       } else {
+               sg_req->words_xferred = wcount;
+       }
+
+       return wcount;
+}
+
 static enum dma_status tegra_dma_tx_status(struct dma_chan *dc,
        dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
@@ -806,6 +870,7 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc,
        enum dma_status ret;
        unsigned long flags;
        unsigned int residual;
+       unsigned int bytes = 0;
 
        ret = dma_cookie_status(dc, cookie, txstate);
        if (ret == DMA_COMPLETE)
@@ -825,6 +890,7 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc,
        list_for_each_entry(sg_req, &tdc->pending_sg_req, node) {
                dma_desc = sg_req->dma_desc;
                if (dma_desc->txd.cookie == cookie) {
+                       bytes = tegra_dma_sg_bytes_xferred(tdc, sg_req);
                        ret = dma_desc->dma_status;
                        goto found;
                }
@@ -836,7 +902,7 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc,
 found:
        if (dma_desc && txstate) {
                residual = dma_desc->bytes_requested -
-                          (dma_desc->bytes_transferred %
+                          ((dma_desc->bytes_transferred + bytes) %
                            dma_desc->bytes_requested);
                dma_set_residue(txstate, residual);
        }
@@ -1441,12 +1507,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
                BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
                BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
        tdma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
-       /*
-        * XXX The hardware appears to support
-        * DMA_RESIDUE_GRANULARITY_BURST-level reporting, but it's
-        * only used by this driver during tegra_dma_terminate_all()
-        */
-       tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+       tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
        tdma->dma_dev.device_config = tegra_dma_slave_config;
        tdma->dma_dev.device_terminate_all = tegra_dma_terminate_all;
        tdma->dma_dev.device_tx_status = tegra_dma_tx_status;
index b33cf6e8ab8ef85b67a885fafa8161ee1c989d68..5f8adf5c1f203f4c1905f728c752ed2dbbfe64b5 100644 (file)
 #define ADMA_CH_CONFIG_MAX_BUFS                                8
 
 #define ADMA_CH_FIFO_CTRL                              0x2c
-#define TEGRA210_ADMA_CH_FIFO_CTRL_OFLWTHRES(val)      (((val) & 0xf) << 24)
-#define TEGRA210_ADMA_CH_FIFO_CTRL_STRVTHRES(val)      (((val) & 0xf) << 16)
 #define TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(val)         (((val) & 0xf) << 8)
 #define TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(val)         ((val) & 0xf)
-#define TEGRA186_ADMA_CH_FIFO_CTRL_OFLWTHRES(val)      (((val) & 0x1f) << 24)
-#define TEGRA186_ADMA_CH_FIFO_CTRL_STRVTHRES(val)      (((val) & 0x1f) << 16)
 #define TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(val)         (((val) & 0x1f) << 8)
 #define TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(val)         ((val) & 0x1f)
 
 
 #define TEGRA_ADMA_BURST_COMPLETE_TIME                 20
 
-#define TEGRA210_FIFO_CTRL_DEFAULT (TEGRA210_ADMA_CH_FIFO_CTRL_OFLWTHRES(1) | \
-                                   TEGRA210_ADMA_CH_FIFO_CTRL_STRVTHRES(1) | \
-                                   TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(3)    | \
+#define TEGRA210_FIFO_CTRL_DEFAULT (TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \
                                    TEGRA210_ADMA_CH_FIFO_CTRL_RXSIZE(3))
 
-#define TEGRA186_FIFO_CTRL_DEFAULT (TEGRA186_ADMA_CH_FIFO_CTRL_OFLWTHRES(1) | \
-                                   TEGRA186_ADMA_CH_FIFO_CTRL_STRVTHRES(1) | \
-                                   TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(3)    | \
+#define TEGRA186_FIFO_CTRL_DEFAULT (TEGRA186_ADMA_CH_FIFO_CTRL_TXSIZE(3) | \
                                    TEGRA186_ADMA_CH_FIFO_CTRL_RXSIZE(3))
 
 #define ADMA_CH_REG_FIELD_VAL(val, mask, shift)        (((val) & mask) << shift)
index ceabdea40ae0fd20aca3e54fb30f2d1e7f562a28..ba7c4f07fcd6f8592cbe95e635b1091b376b9c8d 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
-#include <linux/edma.h>
+#include <linux/bitmap.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #define EDMA_CONT_PARAMS_FIXED_EXACT    1002
 #define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003
 
+/*
+ * 64bit array registers are split into two 32bit registers:
+ * reg0: channel/event 0-31
+ * reg1: channel/event 32-63
+ *
+ * bit 5 in the channel number tells the array index (0/1)
+ * bit 0-4 (0x1f) is the bit offset within the register
+ */
+#define EDMA_REG_ARRAY_INDEX(channel)  ((channel) >> 5)
+#define EDMA_CHANNEL_BIT(channel)      (BIT((channel) & 0x1f))
+
 /* PaRAM slots are laid out like this */
 struct edmacc_param {
        u32 opt;
@@ -169,6 +180,7 @@ struct edma_desc {
        struct list_head                node;
        enum dma_transfer_direction     direction;
        int                             cyclic;
+       bool                            polled;
        int                             absync;
        int                             pset_nr;
        struct edma_chan                *echan;
@@ -412,12 +424,6 @@ static inline void edma_param_or(struct edma_cc *ecc, int offset, int param_no,
        edma_or(ecc, EDMA_PARM + offset + (param_no << 5), or);
 }
 
-static inline void edma_set_bits(int offset, int len, unsigned long *p)
-{
-       for (; len > 0; len--)
-               set_bit(offset + (len - 1), p);
-}
-
 static void edma_assign_priority_to_queue(struct edma_cc *ecc, int queue_no,
                                          int priority)
 {
@@ -441,15 +447,14 @@ static void edma_setup_interrupt(struct edma_chan *echan, bool enable)
 {
        struct edma_cc *ecc = echan->ecc;
        int channel = EDMA_CHAN_SLOT(echan->ch_num);
+       int idx = EDMA_REG_ARRAY_INDEX(channel);
+       int ch_bit = EDMA_CHANNEL_BIT(channel);
 
        if (enable) {
-               edma_shadow0_write_array(ecc, SH_ICR, channel >> 5,
-                                        BIT(channel & 0x1f));
-               edma_shadow0_write_array(ecc, SH_IESR, channel >> 5,
-                                        BIT(channel & 0x1f));
+               edma_shadow0_write_array(ecc, SH_ICR, idx, ch_bit);
+               edma_shadow0_write_array(ecc, SH_IESR, idx, ch_bit);
        } else {
-               edma_shadow0_write_array(ecc, SH_IECR, channel >> 5,
-                                        BIT(channel & 0x1f));
+               edma_shadow0_write_array(ecc, SH_IECR, idx, ch_bit);
        }
 }
 
@@ -587,26 +592,26 @@ static void edma_start(struct edma_chan *echan)
 {
        struct edma_cc *ecc = echan->ecc;
        int channel = EDMA_CHAN_SLOT(echan->ch_num);
-       int j = (channel >> 5);
-       unsigned int mask = BIT(channel & 0x1f);
+       int idx = EDMA_REG_ARRAY_INDEX(channel);
+       int ch_bit = EDMA_CHANNEL_BIT(channel);
 
        if (!echan->hw_triggered) {
                /* EDMA channels without event association */
-               dev_dbg(ecc->dev, "ESR%d %08x\n", j,
-                       edma_shadow0_read_array(ecc, SH_ESR, j));
-               edma_shadow0_write_array(ecc, SH_ESR, j, mask);
+               dev_dbg(ecc->dev, "ESR%d %08x\n", idx,
+                       edma_shadow0_read_array(ecc, SH_ESR, idx));
+               edma_shadow0_write_array(ecc, SH_ESR, idx, ch_bit);
        } else {
                /* EDMA channel with event association */
-               dev_dbg(ecc->dev, "ER%d %08x\n", j,
-                       edma_shadow0_read_array(ecc, SH_ER, j));
+               dev_dbg(ecc->dev, "ER%d %08x\n", idx,
+                       edma_shadow0_read_array(ecc, SH_ER, idx));
                /* Clear any pending event or error */
-               edma_write_array(ecc, EDMA_ECR, j, mask);
-               edma_write_array(ecc, EDMA_EMCR, j, mask);
+               edma_write_array(ecc, EDMA_ECR, idx, ch_bit);
+               edma_write_array(ecc, EDMA_EMCR, idx, ch_bit);
                /* Clear any SER */
-               edma_shadow0_write_array(ecc, SH_SECR, j, mask);
-               edma_shadow0_write_array(ecc, SH_EESR, j, mask);
-               dev_dbg(ecc->dev, "EER%d %08x\n", j,
-                       edma_shadow0_read_array(ecc, SH_EER, j));
+               edma_shadow0_write_array(ecc, SH_SECR, idx, ch_bit);
+               edma_shadow0_write_array(ecc, SH_EESR, idx, ch_bit);
+               dev_dbg(ecc->dev, "EER%d %08x\n", idx,
+                       edma_shadow0_read_array(ecc, SH_EER, idx));
        }
 }
 
@@ -614,19 +619,19 @@ static void edma_stop(struct edma_chan *echan)
 {
        struct edma_cc *ecc = echan->ecc;
        int channel = EDMA_CHAN_SLOT(echan->ch_num);
-       int j = (channel >> 5);
-       unsigned int mask = BIT(channel & 0x1f);
+       int idx = EDMA_REG_ARRAY_INDEX(channel);
+       int ch_bit = EDMA_CHANNEL_BIT(channel);
 
-       edma_shadow0_write_array(ecc, SH_EECR, j, mask);
-       edma_shadow0_write_array(ecc, SH_ECR, j, mask);
-       edma_shadow0_write_array(ecc, SH_SECR, j, mask);
-       edma_write_array(ecc, EDMA_EMCR, j, mask);
+       edma_shadow0_write_array(ecc, SH_EECR, idx, ch_bit);
+       edma_shadow0_write_array(ecc, SH_ECR, idx, ch_bit);
+       edma_shadow0_write_array(ecc, SH_SECR, idx, ch_bit);
+       edma_write_array(ecc, EDMA_EMCR, idx, ch_bit);
 
        /* clear possibly pending completion interrupt */
-       edma_shadow0_write_array(ecc, SH_ICR, j, mask);
+       edma_shadow0_write_array(ecc, SH_ICR, idx, ch_bit);
 
-       dev_dbg(ecc->dev, "EER%d %08x\n", j,
-               edma_shadow0_read_array(ecc, SH_EER, j));
+       dev_dbg(ecc->dev, "EER%d %08x\n", idx,
+               edma_shadow0_read_array(ecc, SH_EER, idx));
 
        /* REVISIT:  consider guarding against inappropriate event
         * chaining by overwriting with dummy_paramset.
@@ -640,45 +645,49 @@ static void edma_stop(struct edma_chan *echan)
 static void edma_pause(struct edma_chan *echan)
 {
        int channel = EDMA_CHAN_SLOT(echan->ch_num);
-       unsigned int mask = BIT(channel & 0x1f);
 
-       edma_shadow0_write_array(echan->ecc, SH_EECR, channel >> 5, mask);
+       edma_shadow0_write_array(echan->ecc, SH_EECR,
+                                EDMA_REG_ARRAY_INDEX(channel),
+                                EDMA_CHANNEL_BIT(channel));
 }
 
 /* Re-enable EDMA hardware events on the specified channel.  */
 static void edma_resume(struct edma_chan *echan)
 {
        int channel = EDMA_CHAN_SLOT(echan->ch_num);
-       unsigned int mask = BIT(channel & 0x1f);
 
-       edma_shadow0_write_array(echan->ecc, SH_EESR, channel >> 5, mask);
+       edma_shadow0_write_array(echan->ecc, SH_EESR,
+                                EDMA_REG_ARRAY_INDEX(channel),
+                                EDMA_CHANNEL_BIT(channel));
 }
 
 static void edma_trigger_channel(struct edma_chan *echan)
 {
        struct edma_cc *ecc = echan->ecc;
        int channel = EDMA_CHAN_SLOT(echan->ch_num);
-       unsigned int mask = BIT(channel & 0x1f);
+       int idx = EDMA_REG_ARRAY_INDEX(channel);
+       int ch_bit = EDMA_CHANNEL_BIT(channel);
 
-       edma_shadow0_write_array(ecc, SH_ESR, (channel >> 5), mask);
+       edma_shadow0_write_array(ecc, SH_ESR, idx, ch_bit);
 
-       dev_dbg(ecc->dev, "ESR%d %08x\n", (channel >> 5),
-               edma_shadow0_read_array(ecc, SH_ESR, (channel >> 5)));
+       dev_dbg(ecc->dev, "ESR%d %08x\n", idx,
+               edma_shadow0_read_array(ecc, SH_ESR, idx));
 }
 
 static void edma_clean_channel(struct edma_chan *echan)
 {
        struct edma_cc *ecc = echan->ecc;
        int channel = EDMA_CHAN_SLOT(echan->ch_num);
-       int j = (channel >> 5);
-       unsigned int mask = BIT(channel & 0x1f);
+       int idx = EDMA_REG_ARRAY_INDEX(channel);
+       int ch_bit = EDMA_CHANNEL_BIT(channel);
 
-       dev_dbg(ecc->dev, "EMR%d %08x\n", j, edma_read_array(ecc, EDMA_EMR, j));
-       edma_shadow0_write_array(ecc, SH_ECR, j, mask);
+       dev_dbg(ecc->dev, "EMR%d %08x\n", idx,
+               edma_read_array(ecc, EDMA_EMR, idx));
+       edma_shadow0_write_array(ecc, SH_ECR, idx, ch_bit);
        /* Clear the corresponding EMR bits */
-       edma_write_array(ecc, EDMA_EMCR, j, mask);
+       edma_write_array(ecc, EDMA_EMCR, idx, ch_bit);
        /* Clear any SER */
-       edma_shadow0_write_array(ecc, SH_SECR, j, mask);
+       edma_shadow0_write_array(ecc, SH_SECR, idx, ch_bit);
        edma_write(ecc, EDMA_CCERRCLR, BIT(16) | BIT(1) | BIT(0));
 }
 
@@ -708,7 +717,8 @@ static int edma_alloc_channel(struct edma_chan *echan,
        int channel = EDMA_CHAN_SLOT(echan->ch_num);
 
        /* ensure access through shadow region 0 */
-       edma_or_array2(ecc, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f));
+       edma_or_array2(ecc, EDMA_DRAE, 0, EDMA_REG_ARRAY_INDEX(channel),
+                      EDMA_CHANNEL_BIT(channel));
 
        /* ensure no events are pending */
        edma_stop(echan);
@@ -1011,6 +1021,7 @@ static int edma_config_pset(struct dma_chan *chan, struct edma_pset *epset,
                src_cidx = cidx;
                dst_bidx = acnt;
                dst_cidx = cidx;
+               epset->addr = src_addr;
        } else {
                dev_err(dev, "%s: direction not implemented yet\n", __func__);
                return -EINVAL;
@@ -1211,8 +1222,9 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy(
 
        edesc->pset[0].param.opt |= ITCCHEN;
        if (nslots == 1) {
-               /* Enable transfer complete interrupt */
-               edesc->pset[0].param.opt |= TCINTEN;
+               /* Enable transfer complete interrupt if requested */
+               if (tx_flags & DMA_PREP_INTERRUPT)
+                       edesc->pset[0].param.opt |= TCINTEN;
        } else {
                /* Enable transfer complete chaining for the first slot */
                edesc->pset[0].param.opt |= TCCHEN;
@@ -1239,9 +1251,14 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy(
                }
 
                edesc->pset[1].param.opt |= ITCCHEN;
-               edesc->pset[1].param.opt |= TCINTEN;
+               /* Enable transfer complete interrupt if requested */
+               if (tx_flags & DMA_PREP_INTERRUPT)
+                       edesc->pset[1].param.opt |= TCINTEN;
        }
 
+       if (!(tx_flags & DMA_PREP_INTERRUPT))
+               edesc->polled = true;
+
        return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags);
 }
 
@@ -1721,7 +1738,11 @@ static u32 edma_residue(struct edma_desc *edesc)
        int loop_count = EDMA_MAX_TR_WAIT_LOOPS;
        struct edma_chan *echan = edesc->echan;
        struct edma_pset *pset = edesc->pset;
-       dma_addr_t done, pos;
+       dma_addr_t done, pos, pos_old;
+       int channel = EDMA_CHAN_SLOT(echan->ch_num);
+       int idx = EDMA_REG_ARRAY_INDEX(channel);
+       int ch_bit = EDMA_CHANNEL_BIT(channel);
+       int event_reg;
        int i;
 
        /*
@@ -1734,16 +1755,20 @@ static u32 edma_residue(struct edma_desc *edesc)
         * "pos" may represent a transfer request that is still being
         * processed by the EDMACC or EDMATC. We will busy wait until
         * any one of the situations occurs:
-        *   1. the DMA hardware is idle
-        *   2. a new transfer request is setup
+        *   1. while and event is pending for the channel
+        *   2. a position updated
         *   3. we hit the loop limit
         */
-       while (edma_read(echan->ecc, EDMA_CCSTAT) & EDMA_CCSTAT_ACTV) {
-               /* check if a new transfer request is setup */
-               if (edma_get_position(echan->ecc,
-                                     echan->slot[0], dst) != pos) {
+       if (is_slave_direction(edesc->direction))
+               event_reg = SH_ER;
+       else
+               event_reg = SH_ESR;
+
+       pos_old = pos;
+       while (edma_shadow0_read_array(echan->ecc, event_reg, idx) & ch_bit) {
+               pos = edma_get_position(echan->ecc, echan->slot[0], dst);
+               if (pos != pos_old)
                        break;
-               }
 
                if (!--loop_count) {
                        dev_dbg_ratelimited(echan->vchan.chan.device->dev,
@@ -1768,6 +1793,12 @@ static u32 edma_residue(struct edma_desc *edesc)
                return edesc->residue_stat;
        }
 
+       /*
+        * If the position is 0, then EDMA loaded the closing dummy slot, the
+        * transfer is completed
+        */
+       if (!pos)
+               return 0;
        /*
         * For SG operation we catch up with the last processed
         * status.
@@ -1796,19 +1827,46 @@ static enum dma_status edma_tx_status(struct dma_chan *chan,
                                      struct dma_tx_state *txstate)
 {
        struct edma_chan *echan = to_edma_chan(chan);
-       struct virt_dma_desc *vdesc;
+       struct dma_tx_state txstate_tmp;
        enum dma_status ret;
        unsigned long flags;
 
        ret = dma_cookie_status(chan, cookie, txstate);
-       if (ret == DMA_COMPLETE || !txstate)
+
+       if (ret == DMA_COMPLETE)
                return ret;
 
+       /* Provide a dummy dma_tx_state for completion checking */
+       if (!txstate)
+               txstate = &txstate_tmp;
+
        spin_lock_irqsave(&echan->vchan.lock, flags);
-       if (echan->edesc && echan->edesc->vdesc.tx.cookie == cookie)
+       if (echan->edesc && echan->edesc->vdesc.tx.cookie == cookie) {
                txstate->residue = edma_residue(echan->edesc);
-       else if ((vdesc = vchan_find_desc(&echan->vchan, cookie)))
-               txstate->residue = to_edma_desc(&vdesc->tx)->residue;
+       } else {
+               struct virt_dma_desc *vdesc = vchan_find_desc(&echan->vchan,
+                                                             cookie);
+
+               if (vdesc)
+                       txstate->residue = to_edma_desc(&vdesc->tx)->residue;
+               else
+                       txstate->residue = 0;
+       }
+
+       /*
+        * Mark the cookie completed if the residue is 0 for non cyclic
+        * transfers
+        */
+       if (ret != DMA_COMPLETE && !txstate->residue &&
+           echan->edesc && echan->edesc->polled &&
+           echan->edesc->vdesc.tx.cookie == cookie) {
+               edma_stop(echan);
+               vchan_cookie_complete(&echan->edesc->vdesc);
+               echan->edesc = NULL;
+               edma_execute(echan);
+               ret = DMA_COMPLETE;
+       }
+
        spin_unlock_irqrestore(&echan->vchan.lock, flags);
 
        return ret;
@@ -2185,11 +2243,13 @@ static struct dma_chan *of_edma_xlate(struct of_phandle_args *dma_spec,
 }
 #endif
 
+static bool edma_filter_fn(struct dma_chan *chan, void *param);
+
 static int edma_probe(struct platform_device *pdev)
 {
        struct edma_soc_info    *info = pdev->dev.platform_data;
        s8                      (*queue_priority_mapping)[2];
-       int                     i, off, ln;
+       int                     i, off;
        const s16               (*rsv_slots)[2];
        const s16               (*xbar_chans)[2];
        int                     irq;
@@ -2273,21 +2333,22 @@ static int edma_probe(struct platform_device *pdev)
 
        ecc->default_queue = info->default_queue;
 
-       for (i = 0; i < ecc->num_slots; i++)
-               edma_write_slot(ecc, i, &dummy_paramset);
-
        if (info->rsv) {
                /* Set the reserved slots in inuse list */
                rsv_slots = info->rsv->rsv_slots;
                if (rsv_slots) {
-                       for (i = 0; rsv_slots[i][0] != -1; i++) {
-                               off = rsv_slots[i][0];
-                               ln = rsv_slots[i][1];
-                               edma_set_bits(off, ln, ecc->slot_inuse);
-                       }
+                       for (i = 0; rsv_slots[i][0] != -1; i++)
+                               bitmap_set(ecc->slot_inuse, rsv_slots[i][0],
+                                          rsv_slots[i][1]);
                }
        }
 
+       for (i = 0; i < ecc->num_slots; i++) {
+               /* Reset only unused - not reserved - paRAM slots */
+               if (!test_bit(i, ecc->slot_inuse))
+                       edma_write_slot(ecc, i, &dummy_paramset);
+       }
+
        /* Clear the xbar mapped channels in unused list */
        xbar_chans = info->xbar_chans;
        if (xbar_chans) {
@@ -2366,11 +2427,10 @@ static int edma_probe(struct platform_device *pdev)
                edma_assign_priority_to_queue(ecc, queue_priority_mapping[i][0],
                                              queue_priority_mapping[i][1]);
 
-       for (i = 0; i < ecc->num_region; i++) {
-               edma_write_array2(ecc, EDMA_DRAE, i, 0, 0x0);
-               edma_write_array2(ecc, EDMA_DRAE, i, 1, 0x0);
-               edma_write_array(ecc, EDMA_QRAE, i, 0x0);
-       }
+       edma_write_array2(ecc, EDMA_DRAE, 0, 0, 0x0);
+       edma_write_array2(ecc, EDMA_DRAE, 0, 1, 0x0);
+       edma_write_array(ecc, EDMA_QRAE, 0, 0x0);
+
        ecc->info = info;
 
        /* Init the dma device and channels */
@@ -2482,8 +2542,9 @@ static int edma_pm_resume(struct device *dev)
        for (i = 0; i < ecc->num_channels; i++) {
                if (echan[i].alloced) {
                        /* ensure access through shadow region 0 */
-                       edma_or_array2(ecc, EDMA_DRAE, 0, i >> 5,
-                                      BIT(i & 0x1f));
+                       edma_or_array2(ecc, EDMA_DRAE, 0,
+                                      EDMA_REG_ARRAY_INDEX(i),
+                                      EDMA_CHANNEL_BIT(i));
 
                        edma_setup_interrupt(&echan[i], true);
 
@@ -2524,7 +2585,7 @@ static struct platform_driver edma_tptc_driver = {
        },
 };
 
-bool edma_filter_fn(struct dma_chan *chan, void *param)
+static bool edma_filter_fn(struct dma_chan *chan, void *param)
 {
        bool match = false;
 
@@ -2539,7 +2600,6 @@ bool edma_filter_fn(struct dma_chan *chan, void *param)
        }
        return match;
 }
-EXPORT_SYMBOL(edma_filter_fn);
 
 static int edma_init(void)
 {
index d07c0d5de7a256388e1806afa4264e91f2f51e2d..6b6ba238b81a756b8e2e8b5c41154283a94531af 100644 (file)
@@ -91,6 +91,7 @@ struct omap_desc {
        bool using_ll;
        enum dma_transfer_direction dir;
        dma_addr_t dev_addr;
+       bool polled;
 
        int32_t fi;             /* for OMAP_DMA_SYNC_PACKET / double indexing */
        int16_t ei;             /* for double indexing */
@@ -202,6 +203,7 @@ static const unsigned es_bytes[] = {
        [CSDP_DATA_TYPE_32] = 4,
 };
 
+static bool omap_dma_filter_fn(struct dma_chan *chan, void *param);
 static struct of_dma_filter_info omap_dma_info = {
        .filter_fn = omap_dma_filter_fn,
 };
@@ -812,31 +814,22 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan,
        dma_cookie_t cookie, struct dma_tx_state *txstate)
 {
        struct omap_chan *c = to_omap_dma_chan(chan);
-       struct virt_dma_desc *vd;
        enum dma_status ret;
        unsigned long flags;
+       struct omap_desc *d = NULL;
 
        ret = dma_cookie_status(chan, cookie, txstate);
-
-       if (!c->paused && c->running) {
-               uint32_t ccr = omap_dma_chan_read(c, CCR);
-               /*
-                * The channel is no longer active, set the return value
-                * accordingly
-                */
-               if (!(ccr & CCR_ENABLE))
-                       ret = DMA_COMPLETE;
-       }
-
-       if (ret == DMA_COMPLETE || !txstate)
+       if (ret == DMA_COMPLETE)
                return ret;
 
        spin_lock_irqsave(&c->vc.lock, flags);
-       vd = vchan_find_desc(&c->vc, cookie);
-       if (vd) {
-               txstate->residue = omap_dma_desc_size(to_omap_dma_desc(&vd->tx));
-       } else if (c->desc && c->desc->vd.tx.cookie == cookie) {
-               struct omap_desc *d = c->desc;
+       if (c->desc && c->desc->vd.tx.cookie == cookie)
+               d = c->desc;
+
+       if (!txstate)
+               goto out;
+
+       if (d) {
                dma_addr_t pos;
 
                if (d->dir == DMA_MEM_TO_DEV)
@@ -848,10 +841,31 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan,
 
                txstate->residue = omap_dma_desc_size_pos(d, pos);
        } else {
-               txstate->residue = 0;
+               struct virt_dma_desc *vd = vchan_find_desc(&c->vc, cookie);
+
+               if (vd)
+                       txstate->residue = omap_dma_desc_size(
+                                               to_omap_dma_desc(&vd->tx));
+               else
+                       txstate->residue = 0;
        }
-       if (ret == DMA_IN_PROGRESS && c->paused)
+
+out:
+       if (ret == DMA_IN_PROGRESS && c->paused) {
                ret = DMA_PAUSED;
+       } else if (d && d->polled && c->running) {
+               uint32_t ccr = omap_dma_chan_read(c, CCR);
+               /*
+                * The channel is no longer active, set the return value
+                * accordingly and mark it as completed
+                */
+               if (!(ccr & CCR_ENABLE)) {
+                       ret = DMA_COMPLETE;
+                       omap_dma_start_desc(c);
+                       vchan_cookie_complete(&d->vd);
+               }
+       }
+
        spin_unlock_irqrestore(&c->vc.lock, flags);
 
        return ret;
@@ -1178,7 +1192,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_memcpy(
        d->ccr = c->ccr;
        d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_POSTINC;
 
-       d->cicr = CICR_DROP_IE | CICR_FRAME_IE;
+       if (tx_flags & DMA_PREP_INTERRUPT)
+               d->cicr |= CICR_FRAME_IE;
+       else
+               d->polled = true;
 
        d->csdp = data_type;
 
@@ -1639,7 +1656,7 @@ static struct platform_driver omap_dma_driver = {
        },
 };
 
-bool omap_dma_filter_fn(struct dma_chan *chan, void *param)
+static bool omap_dma_filter_fn(struct dma_chan *chan, void *param)
 {
        if (chan->device->dev->driver == &omap_dma_driver.driver) {
                struct omap_dmadev *od = to_omap_dma_dev(chan->device);
@@ -1653,7 +1670,6 @@ bool omap_dma_filter_fn(struct dma_chan *chan, void *param)
        }
        return false;
 }
-EXPORT_SYMBOL_GPL(omap_dma_filter_fn);
 
 static int omap_dma_init(void)
 {
index ec65a7430dc45a4b4c1ad2f3d3b0da67def3a83d..fde54687856b8340aee2b84b70777abc1a304d00 100644 (file)
@@ -354,11 +354,8 @@ static int uniphier_mdmac_chan_init(struct platform_device *pdev,
        int irq, ret;
 
        irq = platform_get_irq(pdev, chan_id);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "failed to get IRQ number for ch%d\n",
-                       chan_id);
+       if (irq < 0)
                return irq;
-       }
 
        irq_name = devm_kasprintf(dev, GFP_KERNEL, "uniphier-mio-dmac-ch%d",
                                  chan_id);
index 957c269ce1fd0832a78e576941788b8d6cefae6d..cd60fa6d67501463443c7a1a0fb6e71f80557db1 100644 (file)
@@ -1678,20 +1678,16 @@ static int xgene_dma_get_resources(struct platform_device *pdev,
 
        /* Get DMA error interrupt */
        irq = platform_get_irq(pdev, 0);
-       if (irq <= 0) {
-               dev_err(&pdev->dev, "Failed to get Error IRQ\n");
+       if (irq <= 0)
                return -ENXIO;
-       }
 
        pdma->err_irq = irq;
 
        /* Get DMA Rx ring descriptor interrupts for all DMA channels */
        for (i = 1; i <= XGENE_DMA_MAX_CHANNEL; i++) {
                irq = platform_get_irq(pdev, i);
-               if (irq <= 0) {
-                       dev_err(&pdev->dev, "Failed to get Rx IRQ\n");
+               if (irq <= 0)
                        return -ENXIO;
-               }
 
                pdma->chan[i - 1].rx_irq = irq;
        }
diff --git a/include/linux/edma.h b/include/linux/edma.h
deleted file mode 100644 (file)
index a1307e7..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * TI EDMA DMA engine driver
- *
- * Copyright 2012 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __LINUX_EDMA_H
-#define __LINUX_EDMA_H
-
-struct dma_chan;
-
-#if defined(CONFIG_TI_EDMA) || defined(CONFIG_TI_EDMA_MODULE)
-bool edma_filter_fn(struct dma_chan *, void *);
-#else
-static inline bool edma_filter_fn(struct dma_chan *chan, void *param)
-{
-       return false;
-}
-#endif
-
-#endif
index 840ce551e773b80444c959db3ec5e20e2dbf3a85..ba3cfbb5231204c1d7f4cdc7288b3375a782eb8a 100644 (file)
@@ -1,8 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __LINUX_OMAP_DMA_H
 #define __LINUX_OMAP_DMA_H
-#include <linux/omap-dmaengine.h>
-
 /*
  *  Legacy OMAP DMA handling defines and functions
  *
diff --git a/include/linux/omap-dmaengine.h b/include/linux/omap-dmaengine.h
deleted file mode 100644 (file)
index b6e42f9..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * OMAP DMA Engine support
- */
-#ifndef __LINUX_OMAP_DMAENGINE_H
-#define __LINUX_OMAP_DMAENGINE_H
-
-struct dma_chan;
-
-#if defined(CONFIG_DMA_OMAP) || (defined(CONFIG_DMA_OMAP_MODULE) && defined(MODULE))
-bool omap_dma_filter_fn(struct dma_chan *, void *);
-#else
-static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d)
-{
-       return false;
-}
-#endif
-#endif /* __LINUX_OMAP_DMAENGINE_H */