aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2024-05-02 15:09:35 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2024-05-02 15:09:35 +1000
commit90153fd7aa6a7fcf0d1659db75981cd9d195fe76 (patch)
tree7be08ce195c8556061fa24406cff8e2621689a8a
parentd60eeae4220cf6c9df83bca6cf6ce90e51f3352c (diff)
parent700b2e1eccb4490752227d4339c3d2c3d52d06a7 (diff)
downloadlinux-next-90153fd7aa6a7fcf0d1659db75981cd9d195fe76.tar.gz
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git
Notice: this object is not reachable from any branch.
Notice: this object is not reachable from any branch.
-rw-r--r--Documentation/devicetree/bindings/dma/fsl,edma.yaml139
-rw-r--r--Documentation/devicetree/bindings/dma/fsl,imx-sdma.yaml1
-rw-r--r--Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt95
-rw-r--r--Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml42
-rw-r--r--Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml1
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/dma/amba-pl08x.c4
-rw-r--r--drivers/dma/dma-axi-dmac.c78
-rw-r--r--drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c38
-rw-r--r--drivers/dma/dw-axi-dmac/dw-axi-dmac.h3
-rw-r--r--drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c14
-rw-r--r--drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.h5
-rw-r--r--drivers/dma/fsl-dpaa2-qdma/dpdmai.c113
-rw-r--r--drivers/dma/fsl-dpaa2-qdma/dpdmai.h61
-rw-r--r--drivers/dma/fsl-edma-common.c23
-rw-r--r--drivers/dma/fsl-edma-common.h4
-rw-r--r--drivers/dma/fsl-edma-main.c50
-rw-r--r--drivers/dma/idma64.c4
-rw-r--r--drivers/dma/idxd/cdev.c17
-rw-r--r--drivers/dma/imx-sdma.c97
-rw-r--r--drivers/dma/mcf-edma-main.c4
-rw-r--r--drivers/dma/pch_dma.c5
-rw-r--r--drivers/dma/qcom/hidma.c11
-rw-r--r--drivers/dma/qcom/hidma_mgmt.c109
-rw-r--r--drivers/dma/virt-dma.h10
-rw-r--r--drivers/dma/xilinx/xdma.c1
-rw-r--r--drivers/dma/xilinx/xilinx_dpdma.c10
-rw-r--r--include/linux/dma/imx-dma.h1
28 files changed, 419 insertions, 522 deletions
diff --git a/Documentation/devicetree/bindings/dma/fsl,edma.yaml b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
index aa51d278cb67b4..acfb4b2ee7a960 100644
--- a/Documentation/devicetree/bindings/dma/fsl,edma.yaml
+++ b/Documentation/devicetree/bindings/dma/fsl,edma.yaml
@@ -21,8 +21,8 @@ properties:
- enum:
- fsl,vf610-edma
- fsl,imx7ulp-edma
- - fsl,imx8qm-adma
- fsl,imx8qm-edma
+ - fsl,imx8ulp-edma
- fsl,imx93-edma3
- fsl,imx93-edma4
- fsl,imx95-edma5
@@ -43,6 +43,17 @@ properties:
maxItems: 64
"#dma-cells":
+ description: |
+ Specifies the number of cells needed to encode an DMA channel.
+
+ Encode for cells number 2:
+ cell 0: index of dma channel mux instance.
+ cell 1: peripheral dma request id.
+
+ Encode for cells number 3:
+ cell 0: peripheral dma request id.
+ cell 1: dma channel priority.
+ cell 2: bitmask, defined at include/dt-bindings/dma/fsl-edma.h
enum:
- 2
- 3
@@ -53,11 +64,18 @@ properties:
clocks:
minItems: 1
- maxItems: 2
+ maxItems: 33
clock-names:
minItems: 1
- maxItems: 2
+ maxItems: 33
+
+ power-domains:
+ description:
+ The number of power domains matches the number of channels, arranged
+ in ascending order according to their associated DMA channels.
+ minItems: 1
+ maxItems: 64
big-endian:
description: |
@@ -70,7 +88,6 @@ required:
- compatible
- reg
- interrupts
- - clocks
- dma-channels
allOf:
@@ -80,7 +97,6 @@ allOf:
compatible:
contains:
enum:
- - fsl,imx8qm-adma
- fsl,imx8qm-edma
- fsl,imx93-edma3
- fsl,imx93-edma4
@@ -108,6 +124,7 @@ allOf:
properties:
clocks:
minItems: 2
+ maxItems: 2
clock-names:
items:
- const: dmamux0
@@ -136,6 +153,7 @@ allOf:
properties:
clock:
minItems: 2
+ maxItems: 2
clock-names:
items:
- const: dma
@@ -151,6 +169,58 @@ allOf:
dma-channels:
const: 32
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: fsl,imx8ulp-edma
+ then:
+ properties:
+ clocks:
+ minItems: 33
+ clock-names:
+ minItems: 33
+ items:
+ oneOf:
+ - const: dma
+ - pattern: "^ch(0[0-9]|[1-2][0-9]|3[01])$"
+
+ interrupt-names: false
+ interrupts:
+ minItems: 32
+ "#dma-cells":
+ const: 3
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,vf610-edma
+ - fsl,imx7ulp-edma
+ - fsl,imx93-edma3
+ - fsl,imx93-edma4
+ - fsl,imx95-edma5
+ - fsl,imx8ulp-edma
+ - fsl,ls1028a-edma
+ then:
+ required:
+ - clocks
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx8qm-adma
+ - fsl,imx8qm-edma
+ then:
+ required:
+ - power-domains
+ else:
+ properties:
+ power-domains: false
+
unevaluatedProperties: false
examples:
@@ -206,44 +276,27 @@ examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/clock/imx93-clock.h>
+ #include <dt-bindings/firmware/imx/rsrc.h>
- dma-controller@44000000 {
- compatible = "fsl,imx93-edma3";
- reg = <0x44000000 0x200000>;
+ dma-controller@5a9f0000 {
+ compatible = "fsl,imx8qm-edma";
+ reg = <0x5a9f0000 0x90000>;
#dma-cells = <3>;
- dma-channels = <31>;
- interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX93_CLK_EDMA1_GATE>;
- clock-names = "dma";
+ dma-channels = <8>;
+ interrupts = <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&pd IMX_SC_R_DMA_3_CH0>,
+ <&pd IMX_SC_R_DMA_3_CH1>,
+ <&pd IMX_SC_R_DMA_3_CH2>,
+ <&pd IMX_SC_R_DMA_3_CH3>,
+ <&pd IMX_SC_R_DMA_3_CH4>,
+ <&pd IMX_SC_R_DMA_3_CH5>,
+ <&pd IMX_SC_R_DMA_3_CH6>,
+ <&pd IMX_SC_R_DMA_3_CH7>;
};
diff --git a/Documentation/devicetree/bindings/dma/fsl,imx-sdma.yaml b/Documentation/devicetree/bindings/dma/fsl,imx-sdma.yaml
index 37135fa024f9b8..738b25b88b377b 100644
--- a/Documentation/devicetree/bindings/dma/fsl,imx-sdma.yaml
+++ b/Documentation/devicetree/bindings/dma/fsl,imx-sdma.yaml
@@ -94,6 +94,7 @@ properties:
- SAI: 24
- Multi SAI: 25
- HDMI Audio: 26
+ - I2C: 27
The third cell: transfer priority ID
enum:
diff --git a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt b/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
deleted file mode 100644
index 1ae4748730a854..00000000000000
--- a/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
+++ /dev/null
@@ -1,95 +0,0 @@
-Qualcomm Technologies HIDMA Management interface
-
-Qualcomm Technologies HIDMA is a high speed DMA device. It only supports
-memcpy and memset capabilities. It has been designed for virtualized
-environments.
-
-Each HIDMA HW instance consists of multiple DMA channels. These channels
-share the same bandwidth. The bandwidth utilization can be partitioned
-among channels based on the priority and weight assignments.
-
-There are only two priority levels and 15 weigh assignments possible.
-
-Other parameters here determine how much of the system bus this HIDMA
-instance can use like maximum read/write request and number of bytes to
-read/write in a single burst.
-
-Main node required properties:
-- compatible: "qcom,hidma-mgmt-1.0";
-- reg: Address range for DMA device
-- dma-channels: Number of channels supported by this DMA controller.
-- max-write-burst-bytes: Maximum write burst in bytes that HIDMA can
- occupy the bus for in a single transaction. A memcpy requested is
- fragmented to multiples of this amount. This parameter is used while
- writing into destination memory. Setting this value incorrectly can
- starve other peripherals in the system.
-- max-read-burst-bytes: Maximum read burst in bytes that HIDMA can
- occupy the bus for in a single transaction. A memcpy request is
- fragmented to multiples of this amount. This parameter is used while
- reading the source memory. Setting this value incorrectly can starve
- other peripherals in the system.
-- max-write-transactions: This value is how many times a write burst is
- applied back to back while writing to the destination before yielding
- the bus.
-- max-read-transactions: This value is how many times a read burst is
- applied back to back while reading the source before yielding the bus.
-- channel-reset-timeout-cycles: Channel reset timeout in cycles for this SOC.
- Once a reset is applied to the HW, HW starts a timer for reset operation
- to confirm. If reset is not completed within this time, HW reports reset
- failure.
-
-Sub-nodes:
-
-HIDMA has one or more DMA channels that are used to move data from one
-memory location to another.
-
-When the OS is not in control of the management interface (i.e. it's a guest),
-the channel nodes appear on their own, not under a management node.
-
-Required properties:
-- compatible: must contain "qcom,hidma-1.0" for initial HW or
- "qcom,hidma-1.1"/"qcom,hidma-1.2" for MSI capable HW.
-- reg: Addresses for the transfer and event channel
-- interrupts: Should contain the event interrupt
-- desc-count: Number of asynchronous requests this channel can handle
-- iommus: required a iommu node
-
-Optional properties for MSI:
-- msi-parent : See the generic MSI binding described in
- devicetree/bindings/interrupt-controller/msi.txt for a description of the
- msi-parent property.
-
-Example:
-
-Hypervisor OS configuration:
-
- hidma-mgmt@f9984000 = {
- compatible = "qcom,hidma-mgmt-1.0";
- reg = <0xf9984000 0x15000>;
- dma-channels = <6>;
- max-write-burst-bytes = <1024>;
- max-read-burst-bytes = <1024>;
- max-write-transactions = <31>;
- max-read-transactions = <31>;
- channel-reset-timeout-cycles = <0x500>;
-
- hidma_24: dma-controller@5c050000 {
- compatible = "qcom,hidma-1.0";
- reg = <0 0x5c050000 0x0 0x1000>,
- <0 0x5c0b0000 0x0 0x1000>;
- interrupts = <0 389 0>;
- desc-count = <10>;
- iommus = <&system_mmu>;
- };
- };
-
-Guest OS configuration:
-
- hidma_24: dma-controller@5c050000 {
- compatible = "qcom,hidma-1.0";
- reg = <0 0x5c050000 0x0 0x1000>,
- <0 0x5c0b0000 0x0 0x1000>;
- interrupts = <0 389 0>;
- desc-count = <10>;
- iommus = <&system_mmu>;
- };
diff --git a/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml b/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml
index 5da8291a7de09e..c21a4f073f6c8f 100644
--- a/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml
+++ b/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml
@@ -93,10 +93,10 @@ properties:
data-width:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: Data bus width per each DMA master in bytes.
+ minItems: 1
+ maxItems: 4
items:
- maxItems: 4
- items:
- enum: [4, 8, 16, 32]
+ enum: [4, 8, 16, 32]
data_width:
$ref: /schemas/types.yaml#/definitions/uint32-array
@@ -106,28 +106,28 @@ properties:
deprecated. It' usage is discouraged in favor of data-width one. Moreover
the property incorrectly permits to define data-bus width of 8 and 16
bits, which is impossible in accordance with DW DMAC IP-core data book.
+ minItems: 1
+ maxItems: 4
items:
- maxItems: 4
- items:
- enum:
- - 0 # 8 bits
- - 1 # 16 bits
- - 2 # 32 bits
- - 3 # 64 bits
- - 4 # 128 bits
- - 5 # 256 bits
- default: 0
+ enum:
+ - 0 # 8 bits
+ - 1 # 16 bits
+ - 2 # 32 bits
+ - 3 # 64 bits
+ - 4 # 128 bits
+ - 5 # 256 bits
+ default: 0
multi-block:
$ref: /schemas/types.yaml#/definitions/uint32-array
description: |
LLP-based multi-block transfer supported by hardware per
each DMA channel.
+ minItems: 1
+ maxItems: 8
items:
- maxItems: 8
- items:
- enum: [0, 1]
- default: 1
+ enum: [0, 1]
+ default: 1
snps,max-burst-len:
$ref: /schemas/types.yaml#/definitions/uint32-array
@@ -138,11 +138,11 @@ properties:
will be from 1 to max-burst-len words. It's an array property with one
cell per channel in the units determined by the value set in the
CTLx.SRC_TR_WIDTH/CTLx.DST_TR_WIDTH fields (data width).
+ minItems: 1
+ maxItems: 8
items:
- maxItems: 8
- items:
- enum: [4, 8, 16, 32, 64, 128, 256]
- default: 256
+ enum: [4, 8, 16, 32, 64, 128, 256]
+ default: 256
snps,dma-protection-control:
$ref: /schemas/types.yaml#/definitions/uint32
diff --git a/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml b/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml
index 363cf8bd150da2..525f5f3932f548 100644
--- a/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml
+++ b/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml
@@ -21,6 +21,7 @@ properties:
- snps,axi-dma-1.01a
- intel,kmb-axi-dma
- starfive,jh7110-axi-dma
+ - starfive,jh8100-axi-dma
reg:
minItems: 1
diff --git a/MAINTAINERS b/MAINTAINERS
index 7cef52de661d0b..5f3b4ee12e2c1d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6185,7 +6185,6 @@ F: drivers/mtd/nand/raw/denali*
DESIGNWARE EDMA CORE IP DRIVER
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-R: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
R: Serge Semin <fancer.lancer@gmail.com>
L: dmaengine@vger.kernel.org
S: Maintained
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index fbf048f432bf8f..73a5cfb4da8a6d 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -2855,8 +2855,8 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
}
/* Initialize physical channels */
- pl08x->phy_chans = kzalloc((vd->channels * sizeof(*pl08x->phy_chans)),
- GFP_KERNEL);
+ pl08x->phy_chans = kcalloc(vd->channels, sizeof(*pl08x->phy_chans),
+ GFP_KERNEL);
if (!pl08x->phy_chans) {
ret = -ENOMEM;
goto out_no_phychans;
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 4e339c04fc1ea1..bdb752f1186982 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -1002,6 +1002,16 @@ static int axi_dmac_detect_caps(struct axi_dmac *dmac, unsigned int version)
return 0;
}
+static void axi_dmac_tasklet_kill(void *task)
+{
+ tasklet_kill(task);
+}
+
+static void axi_dmac_free_dma_controller(void *of_node)
+{
+ of_dma_controller_free(of_node);
+}
+
static int axi_dmac_probe(struct platform_device *pdev)
{
struct dma_device *dma_dev;
@@ -1025,14 +1035,10 @@ static int axi_dmac_probe(struct platform_device *pdev)
if (IS_ERR(dmac->base))
return PTR_ERR(dmac->base);
- dmac->clk = devm_clk_get(&pdev->dev, NULL);
+ dmac->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(dmac->clk))
return PTR_ERR(dmac->clk);
- ret = clk_prepare_enable(dmac->clk);
- if (ret < 0)
- return ret;
-
version = axi_dmac_read(dmac, ADI_AXI_REG_VERSION);
if (version >= ADI_AXI_PCORE_VER(4, 3, 'a'))
@@ -1041,7 +1047,7 @@ static int axi_dmac_probe(struct platform_device *pdev)
ret = axi_dmac_parse_dt(&pdev->dev, dmac);
if (ret < 0)
- goto err_clk_disable;
+ return ret;
INIT_LIST_HEAD(&dmac->chan.active_descs);
@@ -1072,7 +1078,7 @@ static int axi_dmac_probe(struct platform_device *pdev)
ret = axi_dmac_detect_caps(dmac, version);
if (ret)
- goto err_clk_disable;
+ return ret;
dma_dev->copy_align = (dmac->chan.address_align_mask + 1);
@@ -1088,57 +1094,42 @@ static int axi_dmac_probe(struct platform_device *pdev)
!AXI_DMAC_DST_COHERENT_GET(ret)) {
dev_err(dmac->dma_dev.dev,
"Coherent DMA not supported in hardware");
- ret = -EINVAL;
- goto err_clk_disable;
+ return -EINVAL;
}
}
- ret = dma_async_device_register(dma_dev);
+ ret = dmaenginem_async_device_register(dma_dev);
+ if (ret)
+ return ret;
+
+ /*
+ * Put the action in here so it get's done before unregistering the DMA
+ * device.
+ */
+ ret = devm_add_action_or_reset(&pdev->dev, axi_dmac_tasklet_kill,
+ &dmac->chan.vchan.task);
if (ret)
- goto err_clk_disable;
+ return ret;
ret = of_dma_controller_register(pdev->dev.of_node,
of_dma_xlate_by_chan_id, dma_dev);
if (ret)
- goto err_unregister_device;
+ return ret;
- ret = request_irq(dmac->irq, axi_dmac_interrupt_handler, IRQF_SHARED,
- dev_name(&pdev->dev), dmac);
+ ret = devm_add_action_or_reset(&pdev->dev, axi_dmac_free_dma_controller,
+ pdev->dev.of_node);
if (ret)
- goto err_unregister_of;
+ return ret;
- platform_set_drvdata(pdev, dmac);
+ ret = devm_request_irq(&pdev->dev, dmac->irq, axi_dmac_interrupt_handler,
+ IRQF_SHARED, dev_name(&pdev->dev), dmac);
+ if (ret)
+ return ret;
regmap = devm_regmap_init_mmio(&pdev->dev, dmac->base,
&axi_dmac_regmap_config);
- if (IS_ERR(regmap)) {
- ret = PTR_ERR(regmap);
- goto err_free_irq;
- }
-
- return 0;
-
-err_free_irq:
- free_irq(dmac->irq, dmac);
-err_unregister_of:
- of_dma_controller_free(pdev->dev.of_node);
-err_unregister_device:
- dma_async_device_unregister(&dmac->dma_dev);
-err_clk_disable:
- clk_disable_unprepare(dmac->clk);
-
- return ret;
-}
-
-static void axi_dmac_remove(struct platform_device *pdev)
-{
- struct axi_dmac *dmac = platform_get_drvdata(pdev);
- of_dma_controller_free(pdev->dev.of_node);
- free_irq(dmac->irq, dmac);
- tasklet_kill(&dmac->chan.vchan.task);
- dma_async_device_unregister(&dmac->dma_dev);
- clk_disable_unprepare(dmac->clk);
+ return PTR_ERR_OR_ZERO(regmap);
}
static const struct of_device_id axi_dmac_of_match_table[] = {
@@ -1153,7 +1144,6 @@ static struct platform_driver axi_dmac_driver = {
.of_match_table = axi_dmac_of_match_table,
},
.probe = axi_dmac_probe,
- .remove_new = axi_dmac_remove,
};
module_platform_driver(axi_dmac_driver);
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index a86a81ff0caa62..fffafa86d964e0 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -302,6 +302,7 @@ static struct axi_dma_desc *axi_desc_alloc(u32 num)
kfree(desc);
return NULL;
}
+ desc->nr_hw_descs = num;
return desc;
}
@@ -328,7 +329,7 @@ static struct axi_dma_lli *axi_desc_get(struct axi_dma_chan *chan,
static void axi_desc_put(struct axi_dma_desc *desc)
{
struct axi_dma_chan *chan = desc->chan;
- int count = atomic_read(&chan->descs_allocated);
+ int count = desc->nr_hw_descs;
struct axi_dma_hw_desc *hw_desc;
int descs_put;
@@ -1139,9 +1140,6 @@ static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan)
/* Remove the completed descriptor from issued list before completing */
list_del(&vd->node);
vchan_cookie_complete(vd);
-
- /* Submit queued descriptors after processing the completed ones */
- axi_chan_start_first_queued(chan);
}
out:
@@ -1445,6 +1443,24 @@ static int parse_device_properties(struct axi_dma_chip *chip)
return 0;
}
+static int axi_req_irqs(struct platform_device *pdev, struct axi_dma_chip *chip)
+{
+ int irq_count = platform_irq_count(pdev);
+ int ret;
+
+ for (int i = 0; i < irq_count; i++) {
+ chip->irq[i] = platform_get_irq(pdev, i);
+ if (chip->irq[i] < 0)
+ return chip->irq[i];
+ ret = devm_request_irq(chip->dev, chip->irq[i], dw_axi_dma_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, chip);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static int dw_probe(struct platform_device *pdev)
{
struct axi_dma_chip *chip;
@@ -1471,10 +1487,6 @@ static int dw_probe(struct platform_device *pdev)
chip->dev = &pdev->dev;
chip->dw->hdata = hdata;
- chip->irq = platform_get_irq(pdev, 0);
- if (chip->irq < 0)
- return chip->irq;
-
chip->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(chip->regs))
return PTR_ERR(chip->regs);
@@ -1515,8 +1527,7 @@ static int dw_probe(struct platform_device *pdev)
if (!dw->chan)
return -ENOMEM;
- ret = devm_request_irq(chip->dev, chip->irq, dw_axi_dma_interrupt,
- IRQF_SHARED, KBUILD_MODNAME, chip);
+ ret = axi_req_irqs(pdev, chip);
if (ret)
return ret;
@@ -1629,7 +1640,9 @@ static void dw_remove(struct platform_device *pdev)
pm_runtime_disable(chip->dev);
axi_dma_suspend(chip);
- devm_free_irq(chip->dev, chip->irq, chip);
+ for (i = 0; i < DMAC_MAX_CHANNELS; i++)
+ if (chip->irq[i] > 0)
+ devm_free_irq(chip->dev, chip->irq[i], chip);
of_dma_controller_free(chip->dev->of_node);
@@ -1653,6 +1666,9 @@ static const struct of_device_id dw_dma_of_id_table[] = {
}, {
.compatible = "starfive,jh7110-axi-dma",
.data = (void *)(AXI_DMA_FLAG_HAS_RESETS | AXI_DMA_FLAG_USE_CFG2),
+ }, {
+ .compatible = "starfive,jh8100-axi-dma",
+ .data = (void *)AXI_DMA_FLAG_HAS_RESETS,
},
{}
};
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
index 454904d996540c..b842e6a8d90d3d 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
@@ -65,7 +65,7 @@ struct dw_axi_dma {
struct axi_dma_chip {
struct device *dev;
- int irq;
+ int irq[DMAC_MAX_CHANNELS];
void __iomem *regs;
void __iomem *apb_regs;
struct clk *core_clk;
@@ -104,6 +104,7 @@ struct axi_dma_desc {
u32 completed_blocks;
u32 length;
u32 period_len;
+ u32 nr_hw_descs;
};
struct axi_dma_chan_config {
diff --git a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c
index 5a8061a307cdaf..36384d01926364 100644
--- a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c
+++ b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.c
@@ -362,7 +362,7 @@ static int __cold dpaa2_qdma_setup(struct fsl_mc_device *ls_dev)
for (i = 0; i < priv->num_pairs; i++) {
err = dpdmai_get_rx_queue(priv->mc_io, 0, ls_dev->mc_handle,
- i, &priv->rx_queue_attr[i]);
+ i, 0, &priv->rx_queue_attr[i]);
if (err) {
dev_err(dev, "dpdmai_get_rx_queue() failed\n");
goto exit;
@@ -370,13 +370,13 @@ static int __cold dpaa2_qdma_setup(struct fsl_mc_device *ls_dev)
ppriv->rsp_fqid = priv->rx_queue_attr[i].fqid;
err = dpdmai_get_tx_queue(priv->mc_io, 0, ls_dev->mc_handle,
- i, &priv->tx_fqid[i]);
+ i, 0, &priv->tx_queue_attr[i]);
if (err) {
dev_err(dev, "dpdmai_get_tx_queue() failed\n");
goto exit;
}
- ppriv->req_fqid = priv->tx_fqid[i];
- ppriv->prio = i;
+ ppriv->req_fqid = priv->tx_queue_attr[i].fqid;
+ ppriv->prio = DPAA2_QDMA_DEFAULT_PRIORITY;
ppriv->priv = priv;
ppriv++;
}
@@ -542,7 +542,7 @@ static int __cold dpaa2_dpdmai_bind(struct dpaa2_qdma_priv *priv)
rx_queue_cfg.dest_cfg.dest_id = ppriv->nctx.dpio_id;
rx_queue_cfg.dest_cfg.priority = ppriv->prio;
err = dpdmai_set_rx_queue(priv->mc_io, 0, ls_dev->mc_handle,
- rx_queue_cfg.dest_cfg.priority,
+ rx_queue_cfg.dest_cfg.priority, 0,
&rx_queue_cfg);
if (err) {
dev_err(dev, "dpdmai_set_rx_queue() failed\n");
@@ -642,7 +642,7 @@ static int dpaa2_dpdmai_init_channels(struct dpaa2_qdma_engine *dpaa2_qdma)
for (i = 0; i < dpaa2_qdma->n_chans; i++) {
dpaa2_chan = &dpaa2_qdma->chans[i];
dpaa2_chan->qdma = dpaa2_qdma;
- dpaa2_chan->fqid = priv->tx_fqid[i % num];
+ dpaa2_chan->fqid = priv->tx_queue_attr[i % num].fqid;
dpaa2_chan->vchan.desc_free = dpaa2_qdma_free_desc;
vchan_init(&dpaa2_chan->vchan, &dpaa2_qdma->dma_dev);
spin_lock_init(&dpaa2_chan->queue_lock);
@@ -802,7 +802,7 @@ static void dpaa2_qdma_shutdown(struct fsl_mc_device *ls_dev)
dpdmai_disable(priv->mc_io, 0, ls_dev->mc_handle);
dpaa2_dpdmai_dpio_unbind(priv);
dpdmai_close(priv->mc_io, 0, ls_dev->mc_handle);
- dpdmai_destroy(priv->mc_io, 0, ls_dev->mc_handle);
+ dpdmai_destroy(priv->mc_io, 0, priv->dpqdma_id, ls_dev->mc_handle);
}
static const struct fsl_mc_device_id dpaa2_qdma_id_table[] = {
diff --git a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.h b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.h
index 03e2f4e0baca83..2c80077cb7c0a7 100644
--- a/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.h
+++ b/drivers/dma/fsl-dpaa2-qdma/dpaa2-qdma.h
@@ -6,6 +6,7 @@
#define DPAA2_QDMA_STORE_SIZE 16
#define NUM_CH 8
+#define DPAA2_QDMA_DEFAULT_PRIORITY 0
struct dpaa2_qdma_sd_d {
u32 rsv:32;
@@ -122,8 +123,8 @@ struct dpaa2_qdma_priv {
struct dpaa2_qdma_engine *dpaa2_qdma;
struct dpaa2_qdma_priv_per_prio *ppriv;
- struct dpdmai_rx_queue_attr rx_queue_attr[DPDMAI_PRIO_NUM];
- u32 tx_fqid[DPDMAI_PRIO_NUM];
+ struct dpdmai_rx_queue_attr rx_queue_attr[DPDMAI_MAX_QUEUE_NUM];
+ struct dpdmai_tx_queue_attr tx_queue_attr[DPDMAI_MAX_QUEUE_NUM];
};
struct dpaa2_qdma_priv_per_prio {
diff --git a/drivers/dma/fsl-dpaa2-qdma/dpdmai.c b/drivers/dma/fsl-dpaa2-qdma/dpdmai.c
index 878662aaa1c2f1..36897b41ee7e5a 100644
--- a/drivers/dma/fsl-dpaa2-qdma/dpdmai.c
+++ b/drivers/dma/fsl-dpaa2-qdma/dpdmai.c
@@ -1,47 +1,52 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright 2019 NXP
+#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/fsl/mc.h>
#include "dpdmai.h"
+#define DEST_TYPE_MASK 0xF
+
struct dpdmai_rsp_get_attributes {
__le32 id;
u8 num_of_priorities;
- u8 pad0[3];
+ u8 num_of_queues;
+ u8 pad0[2];
__le16 major;
__le16 minor;
};
struct dpdmai_cmd_queue {
__le32 dest_id;
- u8 priority;
- u8 queue;
+ u8 dest_priority;
+ union {
+ u8 queue;
+ u8 pri;
+ };
u8 dest_type;
- u8 pad;
+ u8 queue_idx;
__le64 user_ctx;
union {
__le32 options;
__le32 fqid;
};
-};
+} __packed;
struct dpdmai_rsp_get_tx_queue {
__le64 pad;
__le32 fqid;
};
-#define MC_CMD_OP(_cmd, _param, _offset, _width, _type, _arg) \
- ((_cmd).params[_param] |= mc_enc((_offset), (_width), _arg))
+struct dpdmai_cmd_open {
+ __le32 dpdmai_id;
+} __packed;
-/* cmd, param, offset, width, type, arg_name */
-#define DPDMAI_CMD_CREATE(cmd, cfg) \
-do { \
- MC_CMD_OP(cmd, 0, 8, 8, u8, (cfg)->priorities[0]);\
- MC_CMD_OP(cmd, 0, 16, 8, u8, (cfg)->priorities[1]);\
-} while (0)
+struct dpdmai_cmd_destroy {
+ __le32 dpdmai_id;
+} __packed;
static inline u64 mc_enc(int lsoffset, int width, u64 val)
{
@@ -68,16 +73,16 @@ static inline u64 mc_enc(int lsoffset, int width, u64 val)
int dpdmai_open(struct fsl_mc_io *mc_io, u32 cmd_flags,
int dpdmai_id, u16 *token)
{
+ struct dpdmai_cmd_open *cmd_params;
struct fsl_mc_command cmd = { 0 };
- __le64 *cmd_dpdmai_id;
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_OPEN,
cmd_flags, 0);
- cmd_dpdmai_id = cmd.params;
- *cmd_dpdmai_id = cpu_to_le32(dpdmai_id);
+ cmd_params = (struct dpdmai_cmd_open *)&cmd.params;
+ cmd_params->dpdmai_id = cpu_to_le32(dpdmai_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -116,65 +121,26 @@ int dpdmai_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
EXPORT_SYMBOL_GPL(dpdmai_close);
/**
- * dpdmai_create() - Create the DPDMAI object
- * @mc_io: Pointer to MC portal's I/O object
- * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
- * @cfg: Configuration structure
- * @token: Returned token; use in subsequent API calls
- *
- * Create the DPDMAI object, allocate required resources and
- * perform required initialization.
- *
- * The object can be created either by declaring it in the
- * DPL file, or by calling this function.
- *
- * This function returns a unique authentication token,
- * associated with the specific object ID and the specific MC
- * portal; this token must be used in all subsequent calls to
- * this specific object. For objects that are created using the
- * DPL file, call dpdmai_open() function to get an authentication
- * token first.
- *
- * Return: '0' on Success; Error code otherwise.
- */
-int dpdmai_create(struct fsl_mc_io *mc_io, u32 cmd_flags,
- const struct dpdmai_cfg *cfg, u16 *token)
-{
- struct fsl_mc_command cmd = { 0 };
- int err;
-
- /* prepare command */
- cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CREATE,
- cmd_flags, 0);
- DPDMAI_CMD_CREATE(cmd, cfg);
-
- /* send command to mc*/
- err = mc_send_command(mc_io, &cmd);
- if (err)
- return err;
-
- /* retrieve response parameters */
- *token = mc_cmd_hdr_read_token(&cmd);
-
- return 0;
-}
-
-/**
* dpdmai_destroy() - Destroy the DPDMAI object and release all its resources.
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @dpdmai_id: The object id; it must be a valid id within the container that created this object;
* @token: Token of DPDMAI object
*
* Return: '0' on Success; error code otherwise.
*/
-int dpdmai_destroy(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token)
+int dpdmai_destroy(struct fsl_mc_io *mc_io, u32 cmd_flags, u32 dpdmai_id, u16 token)
{
+ struct dpdmai_cmd_destroy *cmd_params;
struct fsl_mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DESTROY,
cmd_flags, token);
+ cmd_params = (struct dpdmai_cmd_destroy *)&cmd.params;
+ cmd_params->dpdmai_id = cpu_to_le32(dpdmai_id);
+
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
@@ -274,6 +240,7 @@ int dpdmai_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags,
attr->version.major = le16_to_cpu(rsp_params->major);
attr->version.minor = le16_to_cpu(rsp_params->minor);
attr->num_of_priorities = rsp_params->num_of_priorities;
+ attr->num_of_queues = rsp_params->num_of_queues;
return 0;
}
@@ -284,13 +251,14 @@ EXPORT_SYMBOL_GPL(dpdmai_get_attributes);
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPDMAI object
+ * @queue_idx: DMA queue index
* @priority: Select the queue relative to number of
* priorities configured at DPDMAI creation
* @cfg: Rx queue configuration
*
* Return: '0' on Success; Error code otherwise.
*/
-int dpdmai_set_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+int dpdmai_set_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u8 queue_idx,
u8 priority, const struct dpdmai_rx_queue_cfg *cfg)
{
struct dpdmai_cmd_queue *cmd_params;
@@ -302,11 +270,12 @@ int dpdmai_set_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
cmd_params = (struct dpdmai_cmd_queue *)cmd.params;
cmd_params->dest_id = cpu_to_le32(cfg->dest_cfg.dest_id);
- cmd_params->priority = cfg->dest_cfg.priority;
- cmd_params->queue = priority;
+ cmd_params->dest_priority = cfg->dest_cfg.priority;
+ cmd_params->pri = priority;
cmd_params->dest_type = cfg->dest_cfg.dest_type;
cmd_params->user_ctx = cpu_to_le64(cfg->user_ctx);
cmd_params->options = cpu_to_le32(cfg->options);
+ cmd_params->queue_idx = queue_idx;
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
@@ -318,13 +287,14 @@ EXPORT_SYMBOL_GPL(dpdmai_set_rx_queue);
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPDMAI object
+ * @queue_idx: DMA Queue index
* @priority: Select the queue relative to number of
* priorities configured at DPDMAI creation
* @attr: Returned Rx queue attributes
*
* Return: '0' on Success; Error code otherwise.
*/
-int dpdmai_get_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
+int dpdmai_get_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u8 queue_idx,
u8 priority, struct dpdmai_rx_queue_attr *attr)
{
struct dpdmai_cmd_queue *cmd_params;
@@ -337,6 +307,7 @@ int dpdmai_get_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
cmd_params = (struct dpdmai_cmd_queue *)cmd.params;
cmd_params->queue = priority;
+ cmd_params->queue_idx = queue_idx;
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -345,8 +316,8 @@ int dpdmai_get_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
/* retrieve response parameters */
attr->dest_cfg.dest_id = le32_to_cpu(cmd_params->dest_id);
- attr->dest_cfg.priority = cmd_params->priority;
- attr->dest_cfg.dest_type = cmd_params->dest_type;
+ attr->dest_cfg.priority = cmd_params->dest_priority;
+ attr->dest_cfg.dest_type = FIELD_GET(DEST_TYPE_MASK, cmd_params->dest_type);
attr->user_ctx = le64_to_cpu(cmd_params->user_ctx);
attr->fqid = le32_to_cpu(cmd_params->fqid);
@@ -359,14 +330,15 @@ EXPORT_SYMBOL_GPL(dpdmai_get_rx_queue);
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPDMAI object
+ * @queue_idx: DMA queue index
* @priority: Select the queue relative to number of
* priorities configured at DPDMAI creation
- * @fqid: Returned Tx queue
+ * @attr: Returned DMA Tx queue attributes
*
* Return: '0' on Success; Error code otherwise.
*/
int dpdmai_get_tx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags,
- u16 token, u8 priority, u32 *fqid)
+ u16 token, u8 queue_idx, u8 priority, struct dpdmai_tx_queue_attr *attr)
{
struct dpdmai_rsp_get_tx_queue *rsp_params;
struct dpdmai_cmd_queue *cmd_params;
@@ -379,6 +351,7 @@ int dpdmai_get_tx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags,
cmd_params = (struct dpdmai_cmd_queue *)cmd.params;
cmd_params->queue = priority;
+ cmd_params->queue_idx = queue_idx;
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
@@ -388,7 +361,7 @@ int dpdmai_get_tx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags,
/* retrieve response parameters */
rsp_params = (struct dpdmai_rsp_get_tx_queue *)cmd.params;
- *fqid = le32_to_cpu(rsp_params->fqid);
+ attr->fqid = le32_to_cpu(rsp_params->fqid);
return 0;
}
diff --git a/drivers/dma/fsl-dpaa2-qdma/dpdmai.h b/drivers/dma/fsl-dpaa2-qdma/dpdmai.h
index b13b9bf0c003e6..3fe7d8327366e4 100644
--- a/drivers/dma/fsl-dpaa2-qdma/dpdmai.h
+++ b/drivers/dma/fsl-dpaa2-qdma/dpdmai.h
@@ -5,14 +5,19 @@
#define __FSL_DPDMAI_H
/* DPDMAI Version */
-#define DPDMAI_VER_MAJOR 2
-#define DPDMAI_VER_MINOR 2
+#define DPDMAI_VER_MAJOR 3
+#define DPDMAI_VER_MINOR 3
-#define DPDMAI_CMD_BASE_VERSION 0
+#define DPDMAI_CMD_BASE_VERSION 1
#define DPDMAI_CMD_ID_OFFSET 4
-#define DPDMAI_CMDID_FORMAT(x) (((x) << DPDMAI_CMD_ID_OFFSET) | \
- DPDMAI_CMD_BASE_VERSION)
+/*
+ * Maximum number of Tx/Rx queues per DPDMAI object
+ */
+#define DPDMAI_MAX_QUEUE_NUM 8
+
+#define DPDMAI_CMDID_FORMAT_V(x, v) (((x) << DPDMAI_CMD_ID_OFFSET) | (v))
+#define DPDMAI_CMDID_FORMAT(x) DPDMAI_CMDID_FORMAT_V(x, DPDMAI_CMD_BASE_VERSION)
/* Command IDs */
#define DPDMAI_CMDID_CLOSE DPDMAI_CMDID_FORMAT(0x800)
@@ -26,18 +31,9 @@
#define DPDMAI_CMDID_RESET DPDMAI_CMDID_FORMAT(0x005)
#define DPDMAI_CMDID_IS_ENABLED DPDMAI_CMDID_FORMAT(0x006)
-#define DPDMAI_CMDID_SET_IRQ DPDMAI_CMDID_FORMAT(0x010)
-#define DPDMAI_CMDID_GET_IRQ DPDMAI_CMDID_FORMAT(0x011)
-#define DPDMAI_CMDID_SET_IRQ_ENABLE DPDMAI_CMDID_FORMAT(0x012)
-#define DPDMAI_CMDID_GET_IRQ_ENABLE DPDMAI_CMDID_FORMAT(0x013)
-#define DPDMAI_CMDID_SET_IRQ_MASK DPDMAI_CMDID_FORMAT(0x014)
-#define DPDMAI_CMDID_GET_IRQ_MASK DPDMAI_CMDID_FORMAT(0x015)
-#define DPDMAI_CMDID_GET_IRQ_STATUS DPDMAI_CMDID_FORMAT(0x016)
-#define DPDMAI_CMDID_CLEAR_IRQ_STATUS DPDMAI_CMDID_FORMAT(0x017)
-
-#define DPDMAI_CMDID_SET_RX_QUEUE DPDMAI_CMDID_FORMAT(0x1A0)
-#define DPDMAI_CMDID_GET_RX_QUEUE DPDMAI_CMDID_FORMAT(0x1A1)
-#define DPDMAI_CMDID_GET_TX_QUEUE DPDMAI_CMDID_FORMAT(0x1A2)
+#define DPDMAI_CMDID_SET_RX_QUEUE DPDMAI_CMDID_FORMAT_V(0x1A0, 2)
+#define DPDMAI_CMDID_GET_RX_QUEUE DPDMAI_CMDID_FORMAT_V(0x1A1, 2)
+#define DPDMAI_CMDID_GET_TX_QUEUE DPDMAI_CMDID_FORMAT_V(0x1A2, 2)
#define MC_CMD_HDR_TOKEN_O 32 /* Token field offset */
#define MC_CMD_HDR_TOKEN_S 16 /* Token field size */
@@ -49,30 +45,32 @@
* Contains initialization APIs and runtime control APIs for DPDMAI
*/
-/**
+/*
* Maximum number of Tx/Rx priorities per DPDMAI object
*/
#define DPDMAI_PRIO_NUM 2
/* DPDMAI queue modification options */
-/**
+/*
* Select to modify the user's context associated with the queue
*/
#define DPDMAI_QUEUE_OPT_USER_CTX 0x1
-/**
+/*
* Select to modify the queue's destination
*/
#define DPDMAI_QUEUE_OPT_DEST 0x2
/**
* struct dpdmai_cfg - Structure representing DPDMAI configuration
+ * @num_queues: Number of the DMA queues
* @priorities: Priorities for the DMA hardware processing; valid priorities are
* configured with values 1-8; the entry following last valid entry
* should be configured with 0
*/
struct dpdmai_cfg {
+ u8 num_queues;
u8 priorities[DPDMAI_PRIO_NUM];
};
@@ -80,20 +78,19 @@ struct dpdmai_cfg {
* struct dpdmai_attr - Structure representing DPDMAI attributes
* @id: DPDMAI object ID
* @version: DPDMAI version
+ * @version.major: DPDMAI major version
+ * @version.minor: DPDMAI minor version
* @num_of_priorities: number of priorities
+ * @num_of_queues: number of the DMA queues
*/
struct dpdmai_attr {
int id;
- /**
- * struct version - DPDMAI version
- * @major: DPDMAI major version
- * @minor: DPDMAI minor version
- */
struct {
u16 major;
u16 minor;
} version;
u8 num_of_priorities;
+ u8 num_of_queues;
};
/**
@@ -158,22 +155,24 @@ struct dpdmai_rx_queue_attr {
u32 fqid;
};
+struct dpdmai_tx_queue_attr {
+ u32 fqid;
+};
+
int dpdmai_open(struct fsl_mc_io *mc_io, u32 cmd_flags,
int dpdmai_id, u16 *token);
int dpdmai_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token);
-int dpdmai_destroy(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token);
-int dpdmai_create(struct fsl_mc_io *mc_io, u32 cmd_flags,
- const struct dpdmai_cfg *cfg, u16 *token);
+int dpdmai_destroy(struct fsl_mc_io *mc_io, u32 cmd_flags, u32 dpdmai_id, u16 token);
int dpdmai_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token);
int dpdmai_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token);
int dpdmai_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token);
int dpdmai_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags,
u16 token, struct dpdmai_attr *attr);
int dpdmai_set_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
- u8 priority, const struct dpdmai_rx_queue_cfg *cfg);
+ u8 queue_idx, u8 priority, const struct dpdmai_rx_queue_cfg *cfg);
int dpdmai_get_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
- u8 priority, struct dpdmai_rx_queue_attr *attr);
+ u8 queue_idx, u8 priority, struct dpdmai_rx_queue_attr *attr);
int dpdmai_get_tx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags,
- u16 token, u8 priority, u32 *fqid);
+ u16 token, u8 queue_idx, u8 priority, struct dpdmai_tx_queue_attr *attr);
#endif /* __FSL_DPDMAI_H */
diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
index b18faa7cfedb9b..d62f5f452a4304 100644
--- a/drivers/dma/fsl-edma-common.c
+++ b/drivers/dma/fsl-edma-common.c
@@ -3,6 +3,8 @@
// Copyright (c) 2013-2014 Freescale Semiconductor, Inc
// Copyright (c) 2017 Sysam, Angelo Dureghello <angelo@sysam.it>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
#include <linux/dmapool.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -74,18 +76,10 @@ static void fsl_edma3_enable_request(struct fsl_edma_chan *fsl_chan)
flags = fsl_edma_drvflags(fsl_chan);
val = edma_readl_chreg(fsl_chan, ch_sbr);
- /* Remote/local swapped wrongly on iMX8 QM Audio edma */
- if (flags & FSL_EDMA_DRV_QUIRK_SWAPPED) {
- if (!fsl_chan->is_rxchan)
- val |= EDMA_V3_CH_SBR_RD;
- else
- val |= EDMA_V3_CH_SBR_WR;
- } else {
- if (fsl_chan->is_rxchan)
- val |= EDMA_V3_CH_SBR_RD;
- else
- val |= EDMA_V3_CH_SBR_WR;
- }
+ if (fsl_chan->is_rxchan)
+ val |= EDMA_V3_CH_SBR_RD;
+ else
+ val |= EDMA_V3_CH_SBR_WR;
if (fsl_chan->is_remote)
val &= ~(EDMA_V3_CH_SBR_RD | EDMA_V3_CH_SBR_WR);
@@ -810,6 +804,9 @@ int fsl_edma_alloc_chan_resources(struct dma_chan *chan)
{
struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+ if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK)
+ clk_prepare_enable(fsl_chan->clk);
+
fsl_chan->tcd_pool = dma_pool_create("tcd_pool", chan->device->dev,
fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_TCD64 ?
sizeof(struct fsl_edma_hw_tcd64) : sizeof(struct fsl_edma_hw_tcd),
@@ -838,6 +835,8 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan)
fsl_chan->tcd_pool = NULL;
fsl_chan->is_sw = false;
fsl_chan->srcid = 0;
+ if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK)
+ clk_disable_unprepare(fsl_chan->clk);
}
void fsl_edma_cleanup_vchan(struct dma_device *dmadev)
diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
index 7bf0aba471a8c7..3f93ebb890b359 100644
--- a/drivers/dma/fsl-edma-common.h
+++ b/drivers/dma/fsl-edma-common.h
@@ -151,7 +151,6 @@ struct fsl_edma_chan {
enum dma_status status;
enum fsl_edma_pm_state pm_state;
bool idle;
- u32 slave_id;
struct fsl_edma_engine *edma;
struct fsl_edma_desc *edesc;
struct dma_slave_config cfg;
@@ -195,8 +194,6 @@ struct fsl_edma_desc {
#define FSL_EDMA_DRV_HAS_PD BIT(5)
#define FSL_EDMA_DRV_HAS_CHCLK BIT(6)
#define FSL_EDMA_DRV_HAS_CHMUX BIT(7)
-/* imx8 QM audio edma remote local swapped */
-#define FSL_EDMA_DRV_QUIRK_SWAPPED BIT(8)
/* control and status register is in tcd address space, edma3 reg layout */
#define FSL_EDMA_DRV_SPLIT_REG BIT(9)
#define FSL_EDMA_DRV_BUS_8BYTE BIT(10)
@@ -238,7 +235,6 @@ struct fsl_edma_engine {
void __iomem *muxbase[DMAMUX_NR];
struct clk *muxclk[DMAMUX_NR];
struct clk *dmaclk;
- struct clk *chclk;
struct mutex fsl_edma_mutex;
const struct fsl_edma_drvdata *drvdata;
u32 n_chans;
diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
index 402f0058a180c8..391e4f13dfeb03 100644
--- a/drivers/dma/fsl-edma-main.c
+++ b/drivers/dma/fsl-edma-main.c
@@ -105,7 +105,8 @@ static struct dma_chan *fsl_edma_xlate(struct of_phandle_args *dma_spec,
if (dma_spec->args_count != 2)
return NULL;
- mutex_lock(&fsl_edma->fsl_edma_mutex);
+ guard(mutex)(&fsl_edma->fsl_edma_mutex);
+
list_for_each_entry_safe(chan, _chan, &fsl_edma->dma_dev.channels, device_node) {
if (chan->client_count)
continue;
@@ -114,15 +115,20 @@ static struct dma_chan *fsl_edma_xlate(struct of_phandle_args *dma_spec,
if (chan) {
chan->device->privatecnt++;
fsl_chan = to_fsl_edma_chan(chan);
- fsl_chan->slave_id = dma_spec->args[1];
- fsl_edma_chan_mux(fsl_chan, fsl_chan->slave_id,
+ fsl_chan->srcid = dma_spec->args[1];
+
+ if (!fsl_chan->srcid) {
+ dev_err(&fsl_chan->pdev->dev, "Invalidate srcid %d\n",
+ fsl_chan->srcid);
+ return NULL;
+ }
+
+ fsl_edma_chan_mux(fsl_chan, fsl_chan->srcid,
true);
- mutex_unlock(&fsl_edma->fsl_edma_mutex);
return chan;
}
}
}
- mutex_unlock(&fsl_edma->fsl_edma_mutex);
return NULL;
}
@@ -342,10 +348,13 @@ static struct fsl_edma_drvdata imx8qm_data = {
.setup_irq = fsl_edma3_irq_init,
};
-static struct fsl_edma_drvdata imx8qm_audio_data = {
- .flags = FSL_EDMA_DRV_QUIRK_SWAPPED | FSL_EDMA_DRV_HAS_PD | FSL_EDMA_DRV_EDMA3,
+static struct fsl_edma_drvdata imx8ulp_data = {
+ .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_CHCLK | FSL_EDMA_DRV_HAS_DMACLK |
+ FSL_EDMA_DRV_EDMA3,
.chreg_space_sz = 0x10000,
.chreg_off = 0x10000,
+ .mux_off = 0x10000 + offsetof(struct fsl_edma3_ch_reg, ch_mux),
+ .mux_skip = 0x10000,
.setup_irq = fsl_edma3_irq_init,
};
@@ -380,7 +389,7 @@ static const struct of_device_id fsl_edma_dt_ids[] = {
{ .compatible = "fsl,ls1028a-edma", .data = &ls1028a_data},
{ .compatible = "fsl,imx7ulp-edma", .data = &imx7ulp_data},
{ .compatible = "fsl,imx8qm-edma", .data = &imx8qm_data},
- { .compatible = "fsl,imx8qm-adma", .data = &imx8qm_audio_data},
+ { .compatible = "fsl,imx8ulp-edma", .data = &imx8ulp_data},
{ .compatible = "fsl,imx93-edma3", .data = &imx93_data3},
{ .compatible = "fsl,imx93-edma4", .data = &imx93_data4},
{ .compatible = "fsl,imx95-edma5", .data = &imx95_data5},
@@ -434,6 +443,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
struct fsl_edma_engine *fsl_edma;
const struct fsl_edma_drvdata *drvdata = NULL;
u32 chan_mask[2] = {0, 0};
+ char clk_name[36];
struct edma_regs *regs;
int chans;
int ret, i;
@@ -476,14 +486,6 @@ static int fsl_edma_probe(struct platform_device *pdev)
}
}
- if (drvdata->flags & FSL_EDMA_DRV_HAS_CHCLK) {
- fsl_edma->chclk = devm_clk_get_enabled(&pdev->dev, "mp");
- if (IS_ERR(fsl_edma->chclk)) {
- dev_err(&pdev->dev, "Missing MP block clock.\n");
- return PTR_ERR(fsl_edma->chclk);
- }
- }
-
ret = of_property_read_variable_u32_array(np, "dma-channel-mask", chan_mask, 1, 2);
if (ret > 0) {
@@ -540,7 +542,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
fsl_chan->edma = fsl_edma;
fsl_chan->pm_state = RUNNING;
- fsl_chan->slave_id = 0;
+ fsl_chan->srcid = 0;
fsl_chan->idle = true;
fsl_chan->dma_dir = DMA_NONE;
fsl_chan->vchan.desc_free = fsl_edma_free_desc;
@@ -551,11 +553,21 @@ static int fsl_edma_probe(struct platform_device *pdev)
+ i * drvdata->chreg_space_sz + drvdata->chreg_off + len;
fsl_chan->mux_addr = fsl_edma->membase + drvdata->mux_off + i * drvdata->mux_skip;
+ if (drvdata->flags & FSL_EDMA_DRV_HAS_CHCLK) {
+ snprintf(clk_name, sizeof(clk_name), "ch%02d", i);
+ fsl_chan->clk = devm_clk_get_enabled(&pdev->dev,
+ (const char *)clk_name);
+
+ if (IS_ERR(fsl_chan->clk))
+ return PTR_ERR(fsl_chan->clk);
+ }
fsl_chan->pdev = pdev;
vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev);
edma_write_tcdreg(fsl_chan, cpu_to_le32(0), csr);
fsl_edma_chan_mux(fsl_chan, 0, false);
+ if (fsl_chan->edma->drvdata->flags & FSL_EDMA_DRV_HAS_CHCLK)
+ clk_disable_unprepare(fsl_chan->clk);
}
ret = fsl_edma->drvdata->setup_irq(pdev, fsl_edma);
@@ -682,8 +694,8 @@ static int fsl_edma_resume_early(struct device *dev)
continue;
fsl_chan->pm_state = RUNNING;
edma_write_tcdreg(fsl_chan, 0, csr);
- if (fsl_chan->slave_id != 0)
- fsl_edma_chan_mux(fsl_chan, fsl_chan->slave_id, true);
+ if (fsl_chan->srcid != 0)
+ fsl_edma_chan_mux(fsl_chan, fsl_chan->srcid, true);
}
if (!(fsl_edma->drvdata->flags & FSL_EDMA_DRV_SPLIT_REG))
diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c
index 1398814d8fbb63..e3505e56784b1a 100644
--- a/drivers/dma/idma64.c
+++ b/drivers/dma/idma64.c
@@ -598,7 +598,9 @@ static int idma64_probe(struct idma64_chip *chip)
idma64->dma.dev = chip->sysdev;
- dma_set_max_seg_size(idma64->dma.dev, IDMA64C_CTLH_BLOCK_TS_MASK);
+ ret = dma_set_max_seg_size(idma64->dma.dev, IDMA64C_CTLH_BLOCK_TS_MASK);
+ if (ret)
+ return ret;
ret = dma_async_device_register(&idma64->dma);
if (ret)
diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c
index c095a2c8f65956..7954e72b6a2ec6 100644
--- a/drivers/dma/idxd/cdev.c
+++ b/drivers/dma/idxd/cdev.c
@@ -516,6 +516,14 @@ static int idxd_user_drv_probe(struct idxd_dev *idxd_dev)
if (idxd->state != IDXD_DEV_ENABLED)
return -ENXIO;
+ mutex_lock(&wq->wq_lock);
+
+ if (!idxd_wq_driver_name_match(wq, dev)) {
+ idxd->cmd_status = IDXD_SCMD_WQ_NO_DRV_NAME;
+ rc = -ENODEV;
+ goto wq_err;
+ }
+
/*
* User type WQ is enabled only when SVA is enabled for two reasons:
* - If no IOMMU or IOMMU Passthrough without SVA, userspace
@@ -531,14 +539,7 @@ static int idxd_user_drv_probe(struct idxd_dev *idxd_dev)
dev_dbg(&idxd->pdev->dev,
"User type WQ cannot be enabled without SVA.\n");
- return -EOPNOTSUPP;
- }
-
- mutex_lock(&wq->wq_lock);
-
- if (!idxd_wq_driver_name_match(wq, dev)) {
- idxd->cmd_status = IDXD_SCMD_WQ_NO_DRV_NAME;
- rc = -ENODEV;
+ rc = -EOPNOTSUPP;
goto wq_err;
}
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 9b42f5e96b1e0a..003e1580b9023b 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -24,6 +24,7 @@
#include <linux/semaphore.h>
#include <linux/spinlock.h>
#include <linux/device.h>
+#include <linux/genalloc.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/slab.h>
@@ -137,7 +138,11 @@
* 0: Source on AIPS
* 12 Destination Bit(DP) 1: Destination on SPBA
* 0: Destination on AIPS
- * 13-15 --------- MUST BE 0
+ * 13 Source FIFO 1: Source is dual FIFO
+ * 0: Source is single FIFO
+ * 14 Destination FIFO 1: Destination is dual FIFO
+ * 0: Destination is single FIFO
+ * 15 --------- MUST BE 0
* 16-23 Higher WML HWML
* 24-27 N Total number of samples after
* which Pad adding/Swallowing
@@ -168,6 +173,8 @@
#define SDMA_WATERMARK_LEVEL_SPDIF BIT(10)
#define SDMA_WATERMARK_LEVEL_SP BIT(11)
#define SDMA_WATERMARK_LEVEL_DP BIT(12)
+#define SDMA_WATERMARK_LEVEL_SD BIT(13)
+#define SDMA_WATERMARK_LEVEL_DD BIT(14)
#define SDMA_WATERMARK_LEVEL_HWML (0xFF << 16)
#define SDMA_WATERMARK_LEVEL_LWE BIT(28)
#define SDMA_WATERMARK_LEVEL_HWE BIT(29)
@@ -175,6 +182,7 @@
#define SDMA_DMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+ BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
#define SDMA_DMA_DIRECTIONS (BIT(DMA_DEV_TO_MEM) | \
@@ -232,20 +240,23 @@ struct sdma_script_start_addrs {
s32 utra_addr;
s32 ram_code_start_addr;
/* End of v1 array */
- s32 mcu_2_ssish_addr;
+ union { s32 v1_end; s32 mcu_2_ssish_addr; };
s32 ssish_2_mcu_addr;
s32 hdmi_dma_addr;
/* End of v2 array */
- s32 zcanfd_2_mcu_addr;
+ union { s32 v2_end; s32 zcanfd_2_mcu_addr; };
s32 zqspi_2_mcu_addr;
s32 mcu_2_ecspi_addr;
s32 mcu_2_sai_addr;
s32 sai_2_mcu_addr;
s32 uart_2_mcu_rom_addr;
s32 uartsh_2_mcu_rom_addr;
+ s32 i2c_2_mcu_addr;
+ s32 mcu_2_i2c_addr;
/* End of v3 array */
- s32 mcu_2_zqspi_addr;
+ union { s32 v3_end; s32 mcu_2_zqspi_addr; };
/* End of v4 array */
+ s32 v4_end[0];
};
/*
@@ -531,6 +542,7 @@ struct sdma_engine {
/* clock ratio for AHB:SDMA core. 1:1 is 1, 2:1 is 0*/
bool clk_ratio;
bool fw_loaded;
+ struct gen_pool *iram_pool;
};
static int sdma_config_write(struct dma_chan *chan,
@@ -1072,6 +1084,11 @@ static int sdma_get_pc(struct sdma_channel *sdmac,
per_2_emi = sdma->script_addrs->sai_2_mcu_addr;
emi_2_per = sdma->script_addrs->mcu_2_sai_addr;
break;
+ case IMX_DMATYPE_I2C:
+ per_2_emi = sdma->script_addrs->i2c_2_mcu_addr;
+ emi_2_per = sdma->script_addrs->mcu_2_i2c_addr;
+ sdmac->is_ram_script = true;
+ break;
case IMX_DMATYPE_HDMI:
emi_2_per = sdma->script_addrs->hdmi_dma_addr;
sdmac->is_ram_script = true;
@@ -1255,6 +1272,16 @@ static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac)
sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_DP;
sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_CONT;
+
+ /*
+ * Limitation: The p2p script support dual fifos in maximum,
+ * So when fifo number is larger than 1, force enable dual
+ * fifos.
+ */
+ if (sdmac->n_fifos_src > 1)
+ sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_SD;
+ if (sdmac->n_fifos_dst > 1)
+ sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_DD;
}
static void sdma_set_watermarklevel_for_sais(struct sdma_channel *sdmac)
@@ -1358,8 +1385,14 @@ static int sdma_request_channel0(struct sdma_engine *sdma)
{
int ret = -EBUSY;
- sdma->bd0 = dma_alloc_coherent(sdma->dev, PAGE_SIZE, &sdma->bd0_phys,
- GFP_NOWAIT);
+ if (sdma->iram_pool)
+ sdma->bd0 = gen_pool_dma_alloc(sdma->iram_pool,
+ sizeof(struct sdma_buffer_descriptor),
+ &sdma->bd0_phys);
+ else
+ sdma->bd0 = dma_alloc_coherent(sdma->dev,
+ sizeof(struct sdma_buffer_descriptor),
+ &sdma->bd0_phys, GFP_NOWAIT);
if (!sdma->bd0) {
ret = -ENOMEM;
goto out;
@@ -1379,10 +1412,14 @@ out:
static int sdma_alloc_bd(struct sdma_desc *desc)
{
u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
+ struct sdma_engine *sdma = desc->sdmac->sdma;
int ret = 0;
- desc->bd = dma_alloc_coherent(desc->sdmac->sdma->dev, bd_size,
- &desc->bd_phys, GFP_NOWAIT);
+ if (sdma->iram_pool)
+ desc->bd = gen_pool_dma_alloc(sdma->iram_pool, bd_size, &desc->bd_phys);
+ else
+ desc->bd = dma_alloc_coherent(sdma->dev, bd_size, &desc->bd_phys, GFP_NOWAIT);
+
if (!desc->bd) {
ret = -ENOMEM;
goto out;
@@ -1394,9 +1431,12 @@ out:
static void sdma_free_bd(struct sdma_desc *desc)
{
u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
+ struct sdma_engine *sdma = desc->sdmac->sdma;
- dma_free_coherent(desc->sdmac->sdma->dev, bd_size, desc->bd,
- desc->bd_phys);
+ if (sdma->iram_pool)
+ gen_pool_free(sdma->iram_pool, (unsigned long)desc->bd, bd_size);
+ else
+ dma_free_coherent(desc->sdmac->sdma->dev, bd_size, desc->bd, desc->bd_phys);
}
static void sdma_desc_free(struct virt_dma_desc *vd)
@@ -1643,6 +1683,9 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
if (count & 3 || sg->dma_address & 3)
goto err_bd_out;
break;
+ case DMA_SLAVE_BUSWIDTH_3_BYTES:
+ bd->mode.command = 3;
+ break;
case DMA_SLAVE_BUSWIDTH_2_BYTES:
bd->mode.command = 2;
if (count & 1 || sg->dma_address & 1)
@@ -1880,10 +1923,17 @@ static void sdma_issue_pending(struct dma_chan *chan)
spin_unlock_irqrestore(&sdmac->vc.lock, flags);
}
-#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 34
-#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2 38
-#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V3 45
-#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V4 46
+#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 \
+(offsetof(struct sdma_script_start_addrs, v1_end) / sizeof(s32))
+
+#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2 \
+(offsetof(struct sdma_script_start_addrs, v2_end) / sizeof(s32))
+
+#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V3 \
+(offsetof(struct sdma_script_start_addrs, v3_end) / sizeof(s32))
+
+#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V4 \
+(offsetof(struct sdma_script_start_addrs, v4_end) / sizeof(s32))
static void sdma_add_scripts(struct sdma_engine *sdma,
const struct sdma_script_start_addrs *addr)
@@ -2068,6 +2118,7 @@ static int sdma_init(struct sdma_engine *sdma)
{
int i, ret;
dma_addr_t ccb_phys;
+ int ccbsize;
ret = clk_enable(sdma->clk_ipg);
if (ret)
@@ -2083,10 +2134,14 @@ static int sdma_init(struct sdma_engine *sdma)
/* Be sure SDMA has not started yet */
writel_relaxed(0, sdma->regs + SDMA_H_C0PTR);
- sdma->channel_control = dma_alloc_coherent(sdma->dev,
- MAX_DMA_CHANNELS * sizeof(struct sdma_channel_control) +
- sizeof(struct sdma_context_data),
- &ccb_phys, GFP_KERNEL);
+ ccbsize = MAX_DMA_CHANNELS * (sizeof(struct sdma_channel_control)
+ + sizeof(struct sdma_context_data));
+
+ if (sdma->iram_pool)
+ sdma->channel_control = gen_pool_dma_alloc(sdma->iram_pool, ccbsize, &ccb_phys);
+ else
+ sdma->channel_control = dma_alloc_coherent(sdma->dev, ccbsize, &ccb_phys,
+ GFP_KERNEL);
if (!sdma->channel_control) {
ret = -ENOMEM;
@@ -2272,6 +2327,12 @@ static int sdma_probe(struct platform_device *pdev)
vchan_init(&sdmac->vc, &sdma->dma_device);
}
+ if (np) {
+ sdma->iram_pool = of_gen_pool_get(np, "iram", 0);
+ if (sdma->iram_pool)
+ dev_info(&pdev->dev, "alloc bd from iram.\n");
+ }
+
ret = sdma_init(sdma);
if (ret)
goto err_init;
diff --git a/drivers/dma/mcf-edma-main.c b/drivers/dma/mcf-edma-main.c
index dba63178387678..78c606f6d0026e 100644
--- a/drivers/dma/mcf-edma-main.c
+++ b/drivers/dma/mcf-edma-main.c
@@ -195,7 +195,7 @@ static int mcf_edma_probe(struct platform_device *pdev)
struct fsl_edma_chan *mcf_chan = &mcf_edma->chans[i];
mcf_chan->edma = mcf_edma;
- mcf_chan->slave_id = i;
+ mcf_chan->srcid = i;
mcf_chan->idle = true;
mcf_chan->dma_dir = DMA_NONE;
mcf_chan->vchan.desc_free = fsl_edma_free_desc;
@@ -277,7 +277,7 @@ bool mcf_edma_filter_fn(struct dma_chan *chan, void *param)
if (chan->device->dev->driver == &mcf_edma_driver.driver) {
struct fsl_edma_chan *mcf_chan = to_fsl_edma_chan(chan);
- return (mcf_chan->slave_id == (uintptr_t)param);
+ return (mcf_chan->srcid == (uintptr_t)param);
}
return false;
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index c359decc07a3f8..6b2793b0769496 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -155,11 +155,6 @@ static inline struct device *chan2dev(struct dma_chan *chan)
return &chan->dev->device;
}
-static inline struct device *chan2parent(struct dma_chan *chan)
-{
- return chan->dev->device.parent;
-}
-
static inline
struct pch_dma_desc *pdc_first_active(struct pch_dma_chan *pd_chan)
{
diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index 202ac95227cbe8..721b4ac0857aaa 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -50,7 +50,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <linux/of_dma.h>
#include <linux/property.h>
#include <linux/delay.h>
#include <linux/acpi.h>
@@ -947,22 +946,12 @@ static const struct acpi_device_id hidma_acpi_ids[] = {
MODULE_DEVICE_TABLE(acpi, hidma_acpi_ids);
#endif
-static const struct of_device_id hidma_match[] = {
- {.compatible = "qcom,hidma-1.0",},
- {.compatible = "qcom,hidma-1.1", .data = (void *)(HIDMA_MSI_CAP),},
- {.compatible = "qcom,hidma-1.2",
- .data = (void *)(HIDMA_MSI_CAP | HIDMA_IDENTITY_CAP),},
- {},
-};
-MODULE_DEVICE_TABLE(of, hidma_match);
-
static struct platform_driver hidma_driver = {
.probe = hidma_probe,
.remove_new = hidma_remove,
.shutdown = hidma_shutdown,
.driver = {
.name = "hidma",
- .of_match_table = hidma_match,
.acpi_match_table = ACPI_PTR(hidma_acpi_ids),
},
};
diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
index 1d675f31252b89..bb883e138ebfb9 100644
--- a/drivers/dma/qcom/hidma_mgmt.c
+++ b/drivers/dma/qcom/hidma_mgmt.c
@@ -7,12 +7,7 @@
#include <linux/dmaengine.h>
#include <linux/acpi.h>
-#include <linux/of.h>
#include <linux/property.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/uaccess.h>
@@ -327,115 +322,13 @@ static const struct acpi_device_id hidma_mgmt_acpi_ids[] = {
MODULE_DEVICE_TABLE(acpi, hidma_mgmt_acpi_ids);
#endif
-static const struct of_device_id hidma_mgmt_match[] = {
- {.compatible = "qcom,hidma-mgmt-1.0",},
- {},
-};
-MODULE_DEVICE_TABLE(of, hidma_mgmt_match);
-
static struct platform_driver hidma_mgmt_driver = {
.probe = hidma_mgmt_probe,
.driver = {
.name = "hidma-mgmt",
- .of_match_table = hidma_mgmt_match,
.acpi_match_table = ACPI_PTR(hidma_mgmt_acpi_ids),
},
};
-#if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ)
-static int object_counter;
-
-static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
-{
- struct platform_device *pdev_parent = of_find_device_by_node(np);
- struct platform_device_info pdevinfo;
- struct device_node *child;
- struct resource *res;
- int ret = 0;
-
- /* allocate a resource array */
- res = kcalloc(3, sizeof(*res), GFP_KERNEL);
- if (!res)
- return -ENOMEM;
-
- for_each_available_child_of_node(np, child) {
- struct platform_device *new_pdev;
-
- ret = of_address_to_resource(child, 0, &res[0]);
- if (!ret)
- goto out;
-
- ret = of_address_to_resource(child, 1, &res[1]);
- if (!ret)
- goto out;
-
- ret = of_irq_to_resource(child, 0, &res[2]);
- if (ret <= 0)
- goto out;
-
- memset(&pdevinfo, 0, sizeof(pdevinfo));
- pdevinfo.fwnode = &child->fwnode;
- pdevinfo.parent = pdev_parent ? &pdev_parent->dev : NULL;
- pdevinfo.name = child->name;
- pdevinfo.id = object_counter++;
- pdevinfo.res = res;
- pdevinfo.num_res = 3;
- pdevinfo.data = NULL;
- pdevinfo.size_data = 0;
- pdevinfo.dma_mask = DMA_BIT_MASK(64);
- new_pdev = platform_device_register_full(&pdevinfo);
- if (IS_ERR(new_pdev)) {
- ret = PTR_ERR(new_pdev);
- goto out;
- }
- new_pdev->dev.of_node = child;
- of_dma_configure(&new_pdev->dev, child, true);
- /*
- * It is assumed that calling of_msi_configure is safe on
- * platforms with or without MSI support.
- */
- of_msi_configure(&new_pdev->dev, child);
- }
-
- kfree(res);
-
- return ret;
-
-out:
- of_node_put(child);
- kfree(res);
-
- return ret;
-}
-#endif
-
-static int __init hidma_mgmt_init(void)
-{
-#if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ)
- struct device_node *child;
-
- for_each_matching_node(child, hidma_mgmt_match) {
- /* device tree based firmware here */
- hidma_mgmt_of_populate_channels(child);
- }
-#endif
- /*
- * We do not check for return value here, as it is assumed that
- * platform_driver_register must not fail. The reason for this is that
- * the (potential) hidma_mgmt_of_populate_channels calls above are not
- * cleaned up if it does fail, and to do this work is quite
- * complicated. In particular, various calls of of_address_to_resource,
- * of_irq_to_resource, platform_device_register_full, of_dma_configure,
- * and of_msi_configure which then call other functions and so on, must
- * be cleaned up - this is not a trivial exercise.
- *
- * Currently, this module is not intended to be unloaded, and there is
- * no module_exit function defined which does the needed cleanup. For
- * this reason, we have to assume success here.
- */
- platform_driver_register(&hidma_mgmt_driver);
-
- return 0;
-}
-module_init(hidma_mgmt_init);
+module_platform_driver(hidma_mgmt_driver);
MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/virt-dma.h b/drivers/dma/virt-dma.h
index e9f5250fbe4dbc..59d9eabc8b6744 100644
--- a/drivers/dma/virt-dma.h
+++ b/drivers/dma/virt-dma.h
@@ -81,6 +81,8 @@ static inline struct dma_async_tx_descriptor *vchan_tx_prep(struct virt_dma_chan
*/
static inline bool vchan_issue_pending(struct virt_dma_chan *vc)
{
+ lockdep_assert_held(&vc->lock);
+
list_splice_tail_init(&vc->desc_submitted, &vc->desc_issued);
return !list_empty(&vc->desc_issued);
}
@@ -96,6 +98,8 @@ static inline void vchan_cookie_complete(struct virt_dma_desc *vd)
struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan);
dma_cookie_t cookie;
+ lockdep_assert_held(&vc->lock);
+
cookie = vd->tx.cookie;
dma_cookie_complete(&vd->tx);
dev_vdbg(vc->chan.device->dev, "txd %p[%x]: marked complete\n",
@@ -146,6 +150,8 @@ static inline void vchan_terminate_vdesc(struct virt_dma_desc *vd)
{
struct virt_dma_chan *vc = to_virt_chan(vd->tx.chan);
+ lockdep_assert_held(&vc->lock);
+
list_add_tail(&vd->node, &vc->desc_terminated);
if (vc->cyclic == vd)
@@ -160,6 +166,8 @@ static inline void vchan_terminate_vdesc(struct virt_dma_desc *vd)
*/
static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc)
{
+ lockdep_assert_held(&vc->lock);
+
return list_first_entry_or_null(&vc->desc_issued,
struct virt_dma_desc, node);
}
@@ -177,6 +185,8 @@ static inline struct virt_dma_desc *vchan_next_desc(struct virt_dma_chan *vc)
static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc,
struct list_head *head)
{
+ lockdep_assert_held(&vc->lock);
+
list_splice_tail_init(&vc->desc_allocated, head);
list_splice_tail_init(&vc->desc_submitted, head);
list_splice_tail_init(&vc->desc_issued, head);
diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c
index 313b217388fe95..e143a733081610 100644
--- a/drivers/dma/xilinx/xdma.c
+++ b/drivers/dma/xilinx/xdma.c
@@ -1307,6 +1307,7 @@ static const struct platform_device_id xdma_id_table[] = {
{ "xdma", 0},
{ },
};
+MODULE_DEVICE_TABLE(platform, xdma_id_table);
static struct platform_driver xdma_driver = {
.driver = {
diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c
index eb0637d90342a6..36bd4825d389d5 100644
--- a/drivers/dma/xilinx/xilinx_dpdma.c
+++ b/drivers/dma/xilinx/xilinx_dpdma.c
@@ -1043,9 +1043,8 @@ static int xilinx_dpdma_chan_stop(struct xilinx_dpdma_chan *chan)
static void xilinx_dpdma_chan_done_irq(struct xilinx_dpdma_chan *chan)
{
struct xilinx_dpdma_tx_desc *active;
- unsigned long flags;
- spin_lock_irqsave(&chan->lock, flags);
+ spin_lock(&chan->lock);
xilinx_dpdma_debugfs_desc_done_irq(chan);
@@ -1057,7 +1056,7 @@ static void xilinx_dpdma_chan_done_irq(struct xilinx_dpdma_chan *chan)
"chan%u: DONE IRQ with no active descriptor!\n",
chan->id);
- spin_unlock_irqrestore(&chan->lock, flags);
+ spin_unlock(&chan->lock);
}
/**
@@ -1072,10 +1071,9 @@ static void xilinx_dpdma_chan_vsync_irq(struct xilinx_dpdma_chan *chan)
{
struct xilinx_dpdma_tx_desc *pending;
struct xilinx_dpdma_sw_desc *sw_desc;
- unsigned long flags;
u32 desc_id;
- spin_lock_irqsave(&chan->lock, flags);
+ spin_lock(&chan->lock);
pending = chan->desc.pending;
if (!chan->running || !pending)
@@ -1108,7 +1106,7 @@ static void xilinx_dpdma_chan_vsync_irq(struct xilinx_dpdma_chan *chan)
spin_unlock(&chan->vchan.lock);
out:
- spin_unlock_irqrestore(&chan->lock, flags);
+ spin_unlock(&chan->lock);
}
/**
diff --git a/include/linux/dma/imx-dma.h b/include/linux/dma/imx-dma.h
index cfec5f946e2376..76a8de9ae15175 100644
--- a/include/linux/dma/imx-dma.h
+++ b/include/linux/dma/imx-dma.h
@@ -41,6 +41,7 @@ enum sdma_peripheral_type {
IMX_DMATYPE_SAI, /* SAI */
IMX_DMATYPE_MULTI_SAI, /* MULTI FIFOs For Audio */
IMX_DMATYPE_HDMI, /* HDMI Audio */
+ IMX_DMATYPE_I2C, /* I2C */
};
enum imx_dma_prio {