mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'dmaengine-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine
Pull dmaengine updates from Vinod Koul: "New HW support: - Freescale i.MX8ULP edma support in edma driver - StarFive JH8100 DMA support in Synopsis axi-dmac driver Updates: - Tracing support for freescale edma driver, updates to dpaa2 driver - Remove unused QCom hidma DT support - Support for i2c dma in imx-sdma - Maintainers update for idxd and edma drivers" * tag 'dmaengine-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (42 commits) MAINTAINERS: Update role for IDXD driver dmaengine: fsl-edma: use _Generic to handle difference type dmaengine: fsl-edma: add trace event support dmaengine: idxd: Avoid unnecessary destruction of file_ida dmaengine: xilinx: xdma: fix module autoloading dt-bindings: dma: fsl-edma: allow 'power-domains' property dt-bindings: dma: fsl-edma: remove 'clocks' from required dmaengine: fsl-dpaa2-qdma: Fix kernel-doc check warning dmaengine: imx-sdma: Add i2c dma support dmaengine: imx-sdma: utilize compiler to calculate ADDRS_ARRAY_SIZE_V<n> dt-bindings: fsl-imx-sdma: Add I2C peripheral types ID dt-bindings: fsl-dma: fsl-edma: clean up unused "fsl,imx8qm-adma" compatible string dmaengine: fsl-edma: clean up unused "fsl,imx8qm-adma" compatible string dt-bindings: dma: Drop unused QCom hidma binding dmaengine: qcom: Drop hidma DT support dmaengine: pl08x: Use kcalloc() instead of kzalloc() dmaengine: fsl-dpaa2-qdma: Update DPDMAI interfaces to version 3 dmaengine: fsl-edma: fix miss mutex unlock at an error return path dmaengine: pch_dma: remove unused function chan2parent dmaengine: fsl-dpaa2-qdma: Add dpdmai_cmd_open ...
This commit is contained in:
@@ -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>;
|
||||
};
|
||||
|
||||
@@ -94,6 +94,7 @@ properties:
|
||||
- SAI: 24
|
||||
- Multi SAI: 25
|
||||
- HDMI Audio: 26
|
||||
- I2C: 27
|
||||
|
||||
The third cell: transfer priority ID
|
||||
enum:
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -6181,7 +6181,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
|
||||
@@ -11090,7 +11089,7 @@ F: drivers/idle/intel_idle.c
|
||||
|
||||
INTEL IDXD DRIVER
|
||||
M: Fenghua Yu <fenghua.yu@intel.com>
|
||||
M: Dave Jiang <dave.jiang@intel.com>
|
||||
R: Dave Jiang <dave.jiang@intel.com>
|
||||
L: dmaengine@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/dma/idxd/*
|
||||
|
||||
@@ -31,10 +31,12 @@ obj-$(CONFIG_DW_AXI_DMAC) += dw-axi-dmac/
|
||||
obj-$(CONFIG_DW_DMAC_CORE) += dw/
|
||||
obj-$(CONFIG_DW_EDMA) += dw-edma/
|
||||
obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
|
||||
fsl-edma-trace-$(CONFIG_TRACING) := fsl-edma-trace.o
|
||||
CFLAGS_fsl-edma-trace.o := -I$(src)
|
||||
obj-$(CONFIG_FSL_DMA) += fsldma.o
|
||||
fsl-edma-objs := fsl-edma-main.o fsl-edma-common.o
|
||||
fsl-edma-objs := fsl-edma-main.o fsl-edma-common.o ${fsl-edma-trace-y}
|
||||
obj-$(CONFIG_FSL_EDMA) += fsl-edma.o
|
||||
mcf-edma-objs := mcf-edma-main.o fsl-edma-common.o
|
||||
mcf-edma-objs := mcf-edma-main.o fsl-edma-common.o ${fsl-edma-trace-y}
|
||||
obj-$(CONFIG_MCF_EDMA) += mcf-edma.o
|
||||
obj-$(CONFIG_FSL_QDMA) += fsl-qdma.o
|
||||
obj-$(CONFIG_FSL_RAID) += fsl_raid.o
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
goto err_clk_disable;
|
||||
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)
|
||||
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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
@@ -115,66 +120,27 @@ 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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
@@ -546,6 +540,8 @@ void fsl_edma_fill_tcd(struct fsl_edma_chan *fsl_chan,
|
||||
csr |= EDMA_TCD_CSR_START;
|
||||
|
||||
fsl_edma_set_tcd_to_le(fsl_chan, tcd, csr, csr);
|
||||
|
||||
trace_edma_fill_tcd(fsl_chan, tcd);
|
||||
}
|
||||
|
||||
static struct fsl_edma_desc *fsl_edma_alloc_desc(struct fsl_edma_chan *fsl_chan,
|
||||
@@ -810,6 +806,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 +837,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)
|
||||
|
||||
@@ -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;
|
||||
@@ -250,13 +246,17 @@ struct fsl_edma_engine {
|
||||
struct fsl_edma_chan chans[] __counted_by(n_chans);
|
||||
};
|
||||
|
||||
static inline u32 fsl_edma_drvflags(struct fsl_edma_chan *fsl_chan)
|
||||
{
|
||||
return fsl_chan->edma->drvdata->flags;
|
||||
}
|
||||
|
||||
#define edma_read_tcdreg_c(chan, _tcd, __name) \
|
||||
(sizeof((_tcd)->__name) == sizeof(u64) ? \
|
||||
edma_readq(chan->edma, &(_tcd)->__name) : \
|
||||
((sizeof((_tcd)->__name) == sizeof(u32)) ? \
|
||||
edma_readl(chan->edma, &(_tcd)->__name) : \
|
||||
edma_readw(chan->edma, &(_tcd)->__name) \
|
||||
))
|
||||
_Generic(((_tcd)->__name), \
|
||||
__iomem __le64 : edma_readq(chan->edma, &(_tcd)->__name), \
|
||||
__iomem __le32 : edma_readl(chan->edma, &(_tcd)->__name), \
|
||||
__iomem __le16 : edma_readw(chan->edma, &(_tcd)->__name) \
|
||||
)
|
||||
|
||||
#define edma_read_tcdreg(chan, __name) \
|
||||
((fsl_edma_drvflags(chan) & FSL_EDMA_DRV_TCD64) ? \
|
||||
@@ -264,23 +264,13 @@ struct fsl_edma_engine {
|
||||
edma_read_tcdreg_c(chan, ((struct fsl_edma_hw_tcd __iomem *)chan->tcd), __name) \
|
||||
)
|
||||
|
||||
#define edma_write_tcdreg_c(chan, _tcd, _val, __name) \
|
||||
do { \
|
||||
switch (sizeof(_tcd->__name)) { \
|
||||
case sizeof(u64): \
|
||||
edma_writeq(chan->edma, (u64 __force)_val, &_tcd->__name); \
|
||||
break; \
|
||||
case sizeof(u32): \
|
||||
edma_writel(chan->edma, (u32 __force)_val, &_tcd->__name); \
|
||||
break; \
|
||||
case sizeof(u16): \
|
||||
edma_writew(chan->edma, (u16 __force)_val, &_tcd->__name); \
|
||||
break; \
|
||||
case sizeof(u8): \
|
||||
edma_writeb(chan->edma, (u8 __force)_val, &_tcd->__name); \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
#define edma_write_tcdreg_c(chan, _tcd, _val, __name) \
|
||||
_Generic((_tcd->__name), \
|
||||
__iomem __le64 : edma_writeq(chan->edma, (u64 __force)(_val), &_tcd->__name), \
|
||||
__iomem __le32 : edma_writel(chan->edma, (u32 __force)(_val), &_tcd->__name), \
|
||||
__iomem __le16 : edma_writew(chan->edma, (u16 __force)(_val), &_tcd->__name), \
|
||||
__iomem u8 : edma_writeb(chan->edma, _val, &_tcd->__name) \
|
||||
)
|
||||
|
||||
#define edma_write_tcdreg(chan, val, __name) \
|
||||
do { \
|
||||
@@ -321,9 +311,11 @@ do { \
|
||||
(((struct fsl_edma_hw_tcd *)_tcd)->_field))
|
||||
|
||||
#define fsl_edma_le_to_cpu(x) \
|
||||
(sizeof(x) == sizeof(u64) ? le64_to_cpu((__force __le64)(x)) : \
|
||||
(sizeof(x) == sizeof(u32) ? le32_to_cpu((__force __le32)(x)) : \
|
||||
le16_to_cpu((__force __le16)(x))))
|
||||
_Generic((x), \
|
||||
__le64 : le64_to_cpu((x)), \
|
||||
__le32 : le32_to_cpu((x)), \
|
||||
__le16 : le16_to_cpu((x)) \
|
||||
)
|
||||
|
||||
#define fsl_edma_get_tcd_to_cpu(_chan, _tcd, _field) \
|
||||
(fsl_edma_drvflags(_chan) & FSL_EDMA_DRV_TCD64 ? \
|
||||
@@ -331,19 +323,11 @@ do { \
|
||||
fsl_edma_le_to_cpu(((struct fsl_edma_hw_tcd *)_tcd)->_field))
|
||||
|
||||
#define fsl_edma_set_tcd_to_le_c(_tcd, _val, _field) \
|
||||
do { \
|
||||
switch (sizeof((_tcd)->_field)) { \
|
||||
case sizeof(u64): \
|
||||
*(__force __le64 *)(&((_tcd)->_field)) = cpu_to_le64(_val); \
|
||||
break; \
|
||||
case sizeof(u32): \
|
||||
*(__force __le32 *)(&((_tcd)->_field)) = cpu_to_le32(_val); \
|
||||
break; \
|
||||
case sizeof(u16): \
|
||||
*(__force __le16 *)(&((_tcd)->_field)) = cpu_to_le16(_val); \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
_Generic(((_tcd)->_field), \
|
||||
__le64 : (_tcd)->_field = cpu_to_le64(_val), \
|
||||
__le32 : (_tcd)->_field = cpu_to_le32(_val), \
|
||||
__le16 : (_tcd)->_field = cpu_to_le16(_val) \
|
||||
)
|
||||
|
||||
#define fsl_edma_set_tcd_to_le(_chan, _tcd, _val, _field) \
|
||||
do { \
|
||||
@@ -353,6 +337,9 @@ do { \
|
||||
fsl_edma_set_tcd_to_le_c((struct fsl_edma_hw_tcd *)_tcd, _val, _field); \
|
||||
} while (0)
|
||||
|
||||
/* Need after struct defination */
|
||||
#include "fsl-edma-trace.h"
|
||||
|
||||
/*
|
||||
* R/W functions for big- or little-endian registers:
|
||||
* The eDMA controller's endian is independent of the CPU core's endian.
|
||||
@@ -371,23 +358,38 @@ static inline u64 edma_readq(struct fsl_edma_engine *edma, void __iomem *addr)
|
||||
h = ioread32(addr + 4);
|
||||
}
|
||||
|
||||
trace_edma_readl(edma, addr, l);
|
||||
trace_edma_readl(edma, addr + 4, h);
|
||||
|
||||
return (h << 32) | l;
|
||||
}
|
||||
|
||||
static inline u32 edma_readl(struct fsl_edma_engine *edma, void __iomem *addr)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (edma->big_endian)
|
||||
return ioread32be(addr);
|
||||
val = ioread32be(addr);
|
||||
else
|
||||
return ioread32(addr);
|
||||
val = ioread32(addr);
|
||||
|
||||
trace_edma_readl(edma, addr, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline u16 edma_readw(struct fsl_edma_engine *edma, void __iomem *addr)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
if (edma->big_endian)
|
||||
return ioread16be(addr);
|
||||
val = ioread16be(addr);
|
||||
else
|
||||
return ioread16(addr);
|
||||
val = ioread16(addr);
|
||||
|
||||
trace_edma_readw(edma, addr, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void edma_writeb(struct fsl_edma_engine *edma,
|
||||
@@ -398,6 +400,8 @@ static inline void edma_writeb(struct fsl_edma_engine *edma,
|
||||
iowrite8(val, (void __iomem *)((unsigned long)addr ^ 0x3));
|
||||
else
|
||||
iowrite8(val, addr);
|
||||
|
||||
trace_edma_writeb(edma, addr, val);
|
||||
}
|
||||
|
||||
static inline void edma_writew(struct fsl_edma_engine *edma,
|
||||
@@ -408,6 +412,8 @@ static inline void edma_writew(struct fsl_edma_engine *edma,
|
||||
iowrite16be(val, (void __iomem *)((unsigned long)addr ^ 0x2));
|
||||
else
|
||||
iowrite16(val, addr);
|
||||
|
||||
trace_edma_writew(edma, addr, val);
|
||||
}
|
||||
|
||||
static inline void edma_writel(struct fsl_edma_engine *edma,
|
||||
@@ -417,6 +423,8 @@ static inline void edma_writel(struct fsl_edma_engine *edma,
|
||||
iowrite32be(val, addr);
|
||||
else
|
||||
iowrite32(val, addr);
|
||||
|
||||
trace_edma_writel(edma, addr, val);
|
||||
}
|
||||
|
||||
static inline void edma_writeq(struct fsl_edma_engine *edma,
|
||||
@@ -429,6 +437,9 @@ static inline void edma_writeq(struct fsl_edma_engine *edma,
|
||||
iowrite32(val & 0xFFFFFFFF, addr);
|
||||
iowrite32(val >> 32, addr + 4);
|
||||
}
|
||||
|
||||
trace_edma_writel(edma, addr, val & 0xFFFFFFFF);
|
||||
trace_edma_writel(edma, addr + 4, val >> 32);
|
||||
}
|
||||
|
||||
static inline struct fsl_edma_chan *to_fsl_edma_chan(struct dma_chan *chan)
|
||||
@@ -436,11 +447,6 @@ static inline struct fsl_edma_chan *to_fsl_edma_chan(struct dma_chan *chan)
|
||||
return container_of(chan, struct fsl_edma_chan, vchan.chan);
|
||||
}
|
||||
|
||||
static inline u32 fsl_edma_drvflags(struct fsl_edma_chan *fsl_chan)
|
||||
{
|
||||
return fsl_chan->edma->drvdata->flags;
|
||||
}
|
||||
|
||||
static inline struct fsl_edma_desc *to_fsl_edma_desc(struct virt_dma_desc *vd)
|
||||
{
|
||||
return container_of(vd, struct fsl_edma_desc, vdesc);
|
||||
|
||||
@@ -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))
|
||||
|
||||
4
drivers/dma/fsl-edma-trace.c
Normal file
4
drivers/dma/fsl-edma-trace.c
Normal file
@@ -0,0 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "fsl-edma-common.h"
|
||||
132
drivers/dma/fsl-edma-trace.h
Normal file
132
drivers/dma/fsl-edma-trace.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2023 NXP.
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM fsl_edma
|
||||
|
||||
#if !defined(__LINUX_FSL_EDMA_TRACE) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define __LINUX_FSL_EDMA_TRACE
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
DECLARE_EVENT_CLASS(edma_log_io,
|
||||
TP_PROTO(struct fsl_edma_engine *edma, void __iomem *addr, u32 value),
|
||||
TP_ARGS(edma, addr, value),
|
||||
TP_STRUCT__entry(
|
||||
__field(struct fsl_edma_engine *, edma)
|
||||
__field(void __iomem *, addr)
|
||||
__field(u32, value)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->edma = edma;
|
||||
__entry->addr = addr;
|
||||
__entry->value = value;
|
||||
),
|
||||
TP_printk("offset %08x: value %08x",
|
||||
(u32)(__entry->addr - __entry->edma->membase), __entry->value)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(edma_log_io, edma_readl,
|
||||
TP_PROTO(struct fsl_edma_engine *edma, void __iomem *addr, u32 value),
|
||||
TP_ARGS(edma, addr, value)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(edma_log_io, edma_writel,
|
||||
TP_PROTO(struct fsl_edma_engine *edma, void __iomem *addr, u32 value),
|
||||
TP_ARGS(edma, addr, value)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(edma_log_io, edma_readw,
|
||||
TP_PROTO(struct fsl_edma_engine *edma, void __iomem *addr, u32 value),
|
||||
TP_ARGS(edma, addr, value)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(edma_log_io, edma_writew,
|
||||
TP_PROTO(struct fsl_edma_engine *edma, void __iomem *addr, u32 value),
|
||||
TP_ARGS(edma, addr, value)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(edma_log_io, edma_readb,
|
||||
TP_PROTO(struct fsl_edma_engine *edma, void __iomem *addr, u32 value),
|
||||
TP_ARGS(edma, addr, value)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(edma_log_io, edma_writeb,
|
||||
TP_PROTO(struct fsl_edma_engine *edma, void __iomem *addr, u32 value),
|
||||
TP_ARGS(edma, addr, value)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(edma_log_tcd,
|
||||
TP_PROTO(struct fsl_edma_chan *chan, void *tcd),
|
||||
TP_ARGS(chan, tcd),
|
||||
TP_STRUCT__entry(
|
||||
__field(u64, saddr)
|
||||
__field(u16, soff)
|
||||
__field(u16, attr)
|
||||
__field(u32, nbytes)
|
||||
__field(u64, slast)
|
||||
__field(u64, daddr)
|
||||
__field(u16, doff)
|
||||
__field(u16, citer)
|
||||
__field(u64, dlast_sga)
|
||||
__field(u16, csr)
|
||||
__field(u16, biter)
|
||||
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->saddr = fsl_edma_get_tcd_to_cpu(chan, tcd, saddr),
|
||||
__entry->soff = fsl_edma_get_tcd_to_cpu(chan, tcd, soff),
|
||||
__entry->attr = fsl_edma_get_tcd_to_cpu(chan, tcd, attr),
|
||||
__entry->nbytes = fsl_edma_get_tcd_to_cpu(chan, tcd, nbytes),
|
||||
__entry->slast = fsl_edma_get_tcd_to_cpu(chan, tcd, slast),
|
||||
__entry->daddr = fsl_edma_get_tcd_to_cpu(chan, tcd, daddr),
|
||||
__entry->doff = fsl_edma_get_tcd_to_cpu(chan, tcd, doff),
|
||||
__entry->citer = fsl_edma_get_tcd_to_cpu(chan, tcd, citer),
|
||||
__entry->dlast_sga = fsl_edma_get_tcd_to_cpu(chan, tcd, dlast_sga),
|
||||
__entry->csr = fsl_edma_get_tcd_to_cpu(chan, tcd, csr),
|
||||
__entry->biter = fsl_edma_get_tcd_to_cpu(chan, tcd, biter);
|
||||
),
|
||||
TP_printk("\n==== TCD =====\n"
|
||||
" saddr: 0x%016llx\n"
|
||||
" soff: 0x%04x\n"
|
||||
" attr: 0x%04x\n"
|
||||
" nbytes: 0x%08x\n"
|
||||
" slast: 0x%016llx\n"
|
||||
" daddr: 0x%016llx\n"
|
||||
" doff: 0x%04x\n"
|
||||
" citer: 0x%04x\n"
|
||||
" dlast: 0x%016llx\n"
|
||||
" csr: 0x%04x\n"
|
||||
" biter: 0x%04x\n",
|
||||
__entry->saddr,
|
||||
__entry->soff,
|
||||
__entry->attr,
|
||||
__entry->nbytes,
|
||||
__entry->slast,
|
||||
__entry->daddr,
|
||||
__entry->doff,
|
||||
__entry->citer,
|
||||
__entry->dlast_sga,
|
||||
__entry->csr,
|
||||
__entry->biter)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(edma_log_tcd, edma_fill_tcd,
|
||||
TP_PROTO(struct fsl_edma_chan *chan, void *tcd),
|
||||
TP_ARGS(chan, tcd)
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
/* this part must be outside header guard */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE fsl-edma-trace
|
||||
|
||||
#include <trace/define_trace.h>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user