dmaengine updates for v6.10
New 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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmZMPDAACgkQfBQHDyUj g0f2dQ/+OSBO+fs8yZJaDjxETLBZFGWX/VoHIaARTUxJYHNhXXZApy6gluMJrPxM /6AeTZO2XCvPdZWzWRslkS2pPLuR8alWJo+SimGB6VoKDAplQLemMNorvM0w1sof rHS38JHkSUifjQtlJyY4AWcP21jVe08MpXaOQmcHfWQ8QaEhacPrq7V46x6OogAO x/QXjiOizo6GMEOpS+CMpR2rrM4sq90GEnN0c7cXg+BXmoiCp586peqqkoAUSUry acIb+vwrGn2WOXrWlYUpFFIvOGVfwiZBP8mnOAhN7KR6xcm0OXbLhDKn3pRofYbo ZaORd2Nae4NJxsiVYUr3Ae+4NwxKhFi7xzY5zNjq9IgKrvOT/22E2fj1wwCfjYEj 7cShuB/1Qq+qcF3zRSWrFjKV3dFCFp2+jMrBTbaZq13Gvt6cEtOqcwT3XiRJ18A/ X8lXWzXEHvLt74AV819cEUg8K3LnoiAuXzfkQgAve8H/bxtlvO+HM6p8s9v164pb mp9mHI5QUNG2A5xzCGQ3KCpBEUhODOml2k2dvkQRWjKUW1zXGl5+67rB6npkKJV7 fw6amW2l/cDYver3tzKQUFWRJgQt8rbNJ3u30o1Ea1NXFrr6gS/RNhVkAm3vkWrq E3kpKgQ4A9RTqlMbvGf+/eel7oOv6RYqZWfc5LW39p3+EAoDWF4= =arjK -----END PGP SIGNATURE----- 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:
commit
d4e034b4c4
@ -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>
|
@ -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)
|
||||
|
@ -577,7 +577,6 @@ void idxd_wq_del_cdev(struct idxd_wq *wq)
|
||||
struct idxd_cdev *idxd_cdev;
|
||||
|
||||
idxd_cdev = wq->idxd_cdev;
|
||||
ida_destroy(&file_ida);
|
||||
wq->idxd_cdev = NULL;
|
||||
cdev_device_del(&idxd_cdev->cdev, cdev_dev(idxd_cdev));
|
||||
put_device(cdev_dev(idxd_cdev));
|
||||
@ -593,6 +592,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
|
||||
@ -608,14 +615,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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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),
|
||||
},
|
||||
};
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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 = {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user