mirror of
https://github.com/a52xq-dev/kernel.git
synced 2026-10-18 21:58:11 +07:00
dmaengine updates for 4.15-rc1
Updates for this cycle include:
- New driver for Spreadtrum dma controller, ST MDMA and DMAMUX controllers
- PM support for IMG MDC drivers
- Updates to bcm-sba-raid driver and improvements to sun6i driver
- Subsystem conversion for:
- timers to use timer_setup()
- remove usage of PCI pool API
- usage of %p format specifier
- Minor updates to bunch of drivers
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQIcBAABAgAGBQJaCn48AAoJEHwUBw8lI4NHTe8P/RpJH8tDat/joT7Hl71stEod
vKa0iSkW2fdwd6PeaRfd+UTloska1NE9rdgfh8pCVveoHjCPQBVBOC7V8DbMtlsi
/IlJjFT74wl2R1aSHcSGoLGsIEyurz+9SK88qCU54OQSjVHSnfmyGI4ycTLQGH9U
zce5JHWHB5MkdftM4eJaSE/t0Md1DBkxadFSQRkwQqqDqoLE7jgJUK0TADRukQqS
fsDYPh/OhYAizAHlmEGuLZQheN0ld5W7n1sGsEnBD88wtBMvYHzAwT17B+BobxEp
jyaoE5nV4AgqWh1mvixrmgKoj2KL3DDC+QeoHYCExdcgIrvc86xN3homx9g9y38a
b99pgDDvXjw4N7S6AmRyQlm/5D0QyjUaoHgGklsaR3ix81dFwDY15aZa8/uQ4EAT
iKH8DxAgOq6aG1MkUycQ/7QTenRbN4yWQQa+Mm5ncoNU8bpazyxf2l5L9OJWpFjX
Q6VagNim+plGeUhpJ4IEfPi7LChXFaYsb1D7A/dqpIRvaYzwsy80b/DNhobGMDF6
eTpny64AKHnozWw/KP5k3DfcYvoU/ytcSsWf8h+CPN7EdLMBqUXFgkVwtyf6WKNc
UPl+2in08GLgfGb+n2IAdaQzlJ4dK2P7f7mx0T4OvRymu35HXd8nJjmMJ5ZyBr1t
Z/0JVfcA66AL+XSt179C
=t9Ix
-----END PGP SIGNATURE-----
Merge tag 'dmaengine-4.15-rc1' of git://git.infradead.org/users/vkoul/slave-dma
Pull dmaengine updates from Vinod Koul:
"Updates for this cycle include:
- new driver for Spreadtrum dma controller, ST MDMA and DMAMUX
controllers
- PM support for IMG MDC drivers
- updates to bcm-sba-raid driver and improvements to sun6i driver
- subsystem conversion for:
- timers to use timer_setup()
- remove usage of PCI pool API
- usage of %p format specifier
- minor updates to bunch of drivers"
* tag 'dmaengine-4.15-rc1' of git://git.infradead.org/users/vkoul/slave-dma: (49 commits)
dmaengine: ti-dma-crossbar: Correct am335x/am43xx mux value type
dmaengine: dmatest: warn user when dma test times out
dmaengine: Revert "rcar-dmac: use TCRB instead of TCR for residue"
dmaengine: stm32_mdma: activate pack/unpack feature
dmaengine: at_hdmac: Remove unnecessary 0x prefixes before %pad
dmaengine: coh901318: Remove unnecessary 0x prefixes before %pad
MAINTAINERS: Step down from a co-maintaner of DW DMAC driver
dmaengine: pch_dma: Replace PCI pool old API
dmaengine: Convert timers to use timer_setup()
dmaengine: sprd: Add Spreadtrum DMA driver
dt-bindings: dmaengine: Add Spreadtrum SC9860 DMA controller
dmaengine: sun6i: Retrieve channel count/max request from devicetree
dmaengine: Build bcm-sba-raid driver as loadable module for iProc SoCs
dmaengine: bcm-sba-raid: Use common GPL comment header
dmaengine: bcm-sba-raid: Use only single mailbox channel
dmaengine: bcm-sba-raid: serialize dma_cookie_complete() using reqs_lock
dmaengine: pl330: fix descriptor allocation fail
dmaengine: rcar-dmac: use TCRB instead of TCR for residue
dmaengine: sun6i: Add support for Allwinner A64 and compatibles
arm64: allwinner: a64: Add devicetree binding for DMA controller
...
This commit is contained in:
commit
23c258763b
35 changed files with 3865 additions and 320 deletions
|
|
@ -3,6 +3,8 @@
|
|||
Required Properties:
|
||||
-compatible: "renesas,<soctype>-usb-dmac", "renesas,usb-dmac" as fallback.
|
||||
Examples with soctypes are:
|
||||
- "renesas,r8a7743-usb-dmac" (RZ/G1M)
|
||||
- "renesas,r8a7745-usb-dmac" (RZ/G1E)
|
||||
- "renesas,r8a7790-usb-dmac" (R-Car H2)
|
||||
- "renesas,r8a7791-usb-dmac" (R-Car M2-W)
|
||||
- "renesas,r8a7793-usb-dmac" (R-Car M2-N)
|
||||
|
|
|
|||
41
Documentation/devicetree/bindings/dma/sprd-dma.txt
Normal file
41
Documentation/devicetree/bindings/dma/sprd-dma.txt
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
* Spreadtrum DMA controller
|
||||
|
||||
This binding follows the generic DMA bindings defined in dma.txt.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "sprd,sc9860-dma".
|
||||
- reg: Should contain DMA registers location and length.
|
||||
- interrupts: Should contain one interrupt shared by all channel.
|
||||
- #dma-cells: must be <1>. Used to represent the number of integer
|
||||
cells in the dmas property of client device.
|
||||
- #dma-channels : Number of DMA channels supported. Should be 32.
|
||||
- clock-names: Should contain the clock of the DMA controller.
|
||||
- clocks: Should contain a clock specifier for each entry in clock-names.
|
||||
|
||||
Example:
|
||||
|
||||
Controller:
|
||||
apdma: dma-controller@20100000 {
|
||||
compatible = "sprd,sc9860-dma";
|
||||
reg = <0x20100000 0x4000>;
|
||||
interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#dma-cells = <1>;
|
||||
#dma-channels = <32>;
|
||||
clock-names = "enable";
|
||||
clocks = <&clk_ap_ahb_gates 5>;
|
||||
};
|
||||
|
||||
|
||||
Client:
|
||||
DMA clients connected to the Spreadtrum DMA controller must use the format
|
||||
described in the dma.txt file, using a two-cell specifier for each channel.
|
||||
The two cells in order are:
|
||||
1. A phandle pointing to the DMA controller.
|
||||
2. The channel id.
|
||||
|
||||
spi0: spi@70a00000{
|
||||
...
|
||||
dma-names = "rx_chn", "tx_chn";
|
||||
dmas = <&apdma 11>, <&apdma 12>;
|
||||
...
|
||||
};
|
||||
|
|
@ -13,6 +13,7 @@ Required properties:
|
|||
- #dma-cells : Must be <4>. See DMA client paragraph for more details.
|
||||
|
||||
Optional properties:
|
||||
- dma-requests : Number of DMA requests supported.
|
||||
- resets: Reference to a reset controller asserting the DMA controller
|
||||
- st,mem2mem: boolean; if defined, it indicates that the controller supports
|
||||
memory-to-memory transfer
|
||||
|
|
@ -34,12 +35,13 @@ Example:
|
|||
#dma-cells = <4>;
|
||||
st,mem2mem;
|
||||
resets = <&rcc 150>;
|
||||
dma-requests = <8>;
|
||||
};
|
||||
|
||||
* DMA client
|
||||
|
||||
DMA clients connected to the STM32 DMA controller must use the format
|
||||
described in the dma.txt file, using a five-cell specifier for each
|
||||
described in the dma.txt file, using a four-cell specifier for each
|
||||
channel: a phandle to the DMA controller plus the following four integer cells:
|
||||
|
||||
1. The channel id
|
||||
|
|
|
|||
84
Documentation/devicetree/bindings/dma/stm32-dmamux.txt
Normal file
84
Documentation/devicetree/bindings/dma/stm32-dmamux.txt
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
STM32 DMA MUX (DMA request router)
|
||||
|
||||
Required properties:
|
||||
- compatible: "st,stm32h7-dmamux"
|
||||
- reg: Memory map for accessing module
|
||||
- #dma-cells: Should be set to <3>.
|
||||
First parameter is request line number.
|
||||
Second is DMA channel configuration
|
||||
Third is Fifo threshold
|
||||
For more details about the three cells, please see
|
||||
stm32-dma.txt documentation binding file
|
||||
- dma-masters: Phandle pointing to the DMA controllers.
|
||||
Several controllers are allowed. Only "st,stm32-dma" DMA
|
||||
compatible are supported.
|
||||
|
||||
Optional properties:
|
||||
- dma-channels : Number of DMA requests supported.
|
||||
- dma-requests : Number of DMAMUX requests supported.
|
||||
- resets: Reference to a reset controller asserting the DMA controller
|
||||
- clocks: Input clock of the DMAMUX instance.
|
||||
|
||||
Example:
|
||||
|
||||
/* DMA controller 1 */
|
||||
dma1: dma-controller@40020000 {
|
||||
compatible = "st,stm32-dma";
|
||||
reg = <0x40020000 0x400>;
|
||||
interrupts = <11>,
|
||||
<12>,
|
||||
<13>,
|
||||
<14>,
|
||||
<15>,
|
||||
<16>,
|
||||
<17>,
|
||||
<47>;
|
||||
clocks = <&timer_clk>;
|
||||
#dma-cells = <4>;
|
||||
st,mem2mem;
|
||||
resets = <&rcc 150>;
|
||||
dma-channels = <8>;
|
||||
dma-requests = <8>;
|
||||
};
|
||||
|
||||
/* DMA controller 1 */
|
||||
dma2: dma@40020400 {
|
||||
compatible = "st,stm32-dma";
|
||||
reg = <0x40020400 0x400>;
|
||||
interrupts = <56>,
|
||||
<57>,
|
||||
<58>,
|
||||
<59>,
|
||||
<60>,
|
||||
<68>,
|
||||
<69>,
|
||||
<70>;
|
||||
clocks = <&timer_clk>;
|
||||
#dma-cells = <4>;
|
||||
st,mem2mem;
|
||||
resets = <&rcc 150>;
|
||||
dma-channels = <8>;
|
||||
dma-requests = <8>;
|
||||
};
|
||||
|
||||
/* DMA mux */
|
||||
dmamux1: dma-router@40020800 {
|
||||
compatible = "st,stm32h7-dmamux";
|
||||
reg = <0x40020800 0x3c>;
|
||||
#dma-cells = <3>;
|
||||
dma-requests = <128>;
|
||||
dma-channels = <16>;
|
||||
dma-masters = <&dma1 &dma2>;
|
||||
clocks = <&timer_clk>;
|
||||
};
|
||||
|
||||
/* DMA client */
|
||||
usart1: serial@40011000 {
|
||||
compatible = "st,stm32-usart", "st,stm32-uart";
|
||||
reg = <0x40011000 0x400>;
|
||||
interrupts = <37>;
|
||||
clocks = <&timer_clk>;
|
||||
dmas = <&dmamux1 41 0x414 0>,
|
||||
<&dmamux1 42 0x414 0>;
|
||||
dma-names = "rx", "tx";
|
||||
};
|
||||
94
Documentation/devicetree/bindings/dma/stm32-mdma.txt
Normal file
94
Documentation/devicetree/bindings/dma/stm32-mdma.txt
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
* STMicroelectronics STM32 MDMA controller
|
||||
|
||||
The STM32 MDMA is a general-purpose direct memory access controller capable of
|
||||
supporting 64 independent DMA channels with 256 HW requests.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "st,stm32h7-mdma"
|
||||
- reg: Should contain MDMA registers location and length. This should include
|
||||
all of the per-channel registers.
|
||||
- interrupts: Should contain the MDMA interrupt.
|
||||
- clocks: Should contain the input clock of the DMA instance.
|
||||
- resets: Reference to a reset controller asserting the DMA controller.
|
||||
- #dma-cells : Must be <5>. See DMA client paragraph for more details.
|
||||
|
||||
Optional properties:
|
||||
- dma-channels: Number of DMA channels supported by the controller.
|
||||
- dma-requests: Number of DMA request signals supported by the controller.
|
||||
- st,ahb-addr-masks: Array of u32 mask to list memory devices addressed via
|
||||
AHB bus.
|
||||
|
||||
Example:
|
||||
|
||||
mdma1: dma@52000000 {
|
||||
compatible = "st,stm32h7-mdma";
|
||||
reg = <0x52000000 0x1000>;
|
||||
interrupts = <122>;
|
||||
clocks = <&timer_clk>;
|
||||
resets = <&rcc 992>;
|
||||
#dma-cells = <5>;
|
||||
dma-channels = <16>;
|
||||
dma-requests = <32>;
|
||||
st,ahb-addr-masks = <0x20000000>, <0x00000000>;
|
||||
};
|
||||
|
||||
* DMA client
|
||||
|
||||
DMA clients connected to the STM32 MDMA controller must use the format
|
||||
described in the dma.txt file, using a five-cell specifier for each channel:
|
||||
a phandle to the MDMA controller plus the following five integer cells:
|
||||
|
||||
1. The request line number
|
||||
2. The priority level
|
||||
0x00: Low
|
||||
0x01: Medium
|
||||
0x10: High
|
||||
0x11: Very high
|
||||
3. A 32bit mask specifying the DMA channel configuration
|
||||
-bit 0-1: Source increment mode
|
||||
0x00: Source address pointer is fixed
|
||||
0x10: Source address pointer is incremented after each data transfer
|
||||
0x11: Source address pointer is decremented after each data transfer
|
||||
-bit 2-3: Destination increment mode
|
||||
0x00: Destination address pointer is fixed
|
||||
0x10: Destination address pointer is incremented after each data
|
||||
transfer
|
||||
0x11: Destination address pointer is decremented after each data
|
||||
transfer
|
||||
-bit 8-9: Source increment offset size
|
||||
0x00: byte (8bit)
|
||||
0x01: half-word (16bit)
|
||||
0x10: word (32bit)
|
||||
0x11: double-word (64bit)
|
||||
-bit 10-11: Destination increment offset size
|
||||
0x00: byte (8bit)
|
||||
0x01: half-word (16bit)
|
||||
0x10: word (32bit)
|
||||
0x11: double-word (64bit)
|
||||
-bit 25-18: The number of bytes to be transferred in a single transfer
|
||||
(min = 1 byte, max = 128 bytes)
|
||||
-bit 29:28: Trigger Mode
|
||||
0x00: Each MDMA request triggers a buffer transfer (max 128 bytes)
|
||||
0x01: Each MDMA request triggers a block transfer (max 64K bytes)
|
||||
0x10: Each MDMA request triggers a repeated block transfer
|
||||
0x11: Each MDMA request triggers a linked list transfer
|
||||
4. A 32bit value specifying the register to be used to acknowledge the request
|
||||
if no HW ack signal is used by the MDMA client
|
||||
5. A 32bit mask specifying the value to be written to acknowledge the request
|
||||
if no HW ack signal is used by the MDMA client
|
||||
|
||||
Example:
|
||||
|
||||
i2c4: i2c@5c002000 {
|
||||
compatible = "st,stm32f7-i2c";
|
||||
reg = <0x5c002000 0x400>;
|
||||
interrupts = <95>,
|
||||
<96>;
|
||||
clocks = <&timer_clk>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
dmas = <&mdma1 36 0x0 0x40008 0x0 0x0>,
|
||||
<&mdma1 37 0x0 0x40002 0x0 0x0>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
@ -27,6 +27,32 @@ Example:
|
|||
#dma-cells = <1>;
|
||||
};
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
For A64 DMA controller:
|
||||
|
||||
Required properties:
|
||||
- compatible: "allwinner,sun50i-a64-dma"
|
||||
- dma-channels: Number of DMA channels supported by the controller.
|
||||
Refer to Documentation/devicetree/bindings/dma/dma.txt
|
||||
- all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells
|
||||
|
||||
Optional properties:
|
||||
- dma-requests: Number of DMA request signals supported by the controller.
|
||||
Refer to Documentation/devicetree/bindings/dma/dma.txt
|
||||
|
||||
Example:
|
||||
dma: dma-controller@1c02000 {
|
||||
compatible = "allwinner,sun50i-a64-dma";
|
||||
reg = <0x01c02000 0x1000>;
|
||||
interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&ccu CLK_BUS_DMA>;
|
||||
dma-channels = <8>;
|
||||
dma-requests = <27>;
|
||||
resets = <&ccu RST_BUS_DMA>;
|
||||
#dma-cells = <1>;
|
||||
};
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Clients:
|
||||
|
||||
DMA clients connected to the A31 DMA controller must use the format
|
||||
|
|
|
|||
|
|
@ -12947,7 +12947,7 @@ F: Documentation/devicetree/bindings/arc/axs10*
|
|||
|
||||
SYNOPSYS DESIGNWARE DMAC DRIVER
|
||||
M: Viresh Kumar <vireshk@kernel.org>
|
||||
M: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
S: Maintained
|
||||
F: include/linux/dma/dw.h
|
||||
F: include/linux/platform_data/dma-dw.h
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ config BCM_SBA_RAID
|
|||
select DMA_ENGINE_RAID
|
||||
select ASYNC_TX_DISABLE_XOR_VAL_DMA
|
||||
select ASYNC_TX_DISABLE_PQ_VAL_DMA
|
||||
default ARCH_BCM_IPROC
|
||||
default m if ARCH_BCM_IPROC
|
||||
help
|
||||
Enable support for Broadcom SBA RAID Engine. The SBA RAID
|
||||
engine is available on most of the Broadcom iProc SoCs. It
|
||||
|
|
@ -483,6 +483,35 @@ config STM32_DMA
|
|||
If you have a board based on such a MCU and wish to use DMA say Y
|
||||
here.
|
||||
|
||||
config STM32_DMAMUX
|
||||
bool "STMicroelectronics STM32 dma multiplexer support"
|
||||
depends on STM32_DMA || COMPILE_TEST
|
||||
help
|
||||
Enable support for the on-chip DMA multiplexer on STMicroelectronics
|
||||
STM32 MCUs.
|
||||
If you have a board based on such a MCU and wish to use DMAMUX say Y
|
||||
here.
|
||||
|
||||
config STM32_MDMA
|
||||
bool "STMicroelectronics STM32 master dma support"
|
||||
depends on ARCH_STM32 || COMPILE_TEST
|
||||
depends on OF
|
||||
select DMA_ENGINE
|
||||
select DMA_VIRTUAL_CHANNELS
|
||||
help
|
||||
Enable support for the on-chip MDMA controller on STMicroelectronics
|
||||
STM32 platforms.
|
||||
If you have a board based on STM32 SoC and wish to use the master DMA
|
||||
say Y here.
|
||||
|
||||
config SPRD_DMA
|
||||
tristate "Spreadtrum DMA support"
|
||||
depends on ARCH_SPRD || COMPILE_TEST
|
||||
select DMA_ENGINE
|
||||
select DMA_VIRTUAL_CHANNELS
|
||||
help
|
||||
Enable support for the on-chip DMA controller on Spreadtrum platform.
|
||||
|
||||
config S3C24XX_DMAC
|
||||
bool "Samsung S3C24XX DMA support"
|
||||
depends on ARCH_S3C24XX || COMPILE_TEST
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ obj-$(CONFIG_RENESAS_DMA) += sh/
|
|||
obj-$(CONFIG_SIRF_DMA) += sirf-dma.o
|
||||
obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
|
||||
obj-$(CONFIG_STM32_DMA) += stm32-dma.o
|
||||
obj-$(CONFIG_STM32_DMAMUX) += stm32-dmamux.o
|
||||
obj-$(CONFIG_STM32_MDMA) += stm32-mdma.o
|
||||
obj-$(CONFIG_SPRD_DMA) += sprd-dma.o
|
||||
obj-$(CONFIG_S3C24XX_DMAC) += s3c24xx-dma.o
|
||||
obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
|
||||
obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ static void vdbg_dump_regs(struct at_dma_chan *atchan) {}
|
|||
static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
|
||||
{
|
||||
dev_crit(chan2dev(&atchan->chan_common),
|
||||
" desc: s%pad d%pad ctrl0x%x:0x%x l0x%pad\n",
|
||||
"desc: s%pad d%pad ctrl0x%x:0x%x l%pad\n",
|
||||
&lli->saddr, &lli->daddr,
|
||||
lli->ctrla, lli->ctrlb, &lli->dscr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Broadcom
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation version 2.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -25,11 +30,8 @@
|
|||
*
|
||||
* The Broadcom SBA RAID driver does not require any register programming
|
||||
* except submitting request to SBA hardware device via mailbox channels.
|
||||
* This driver implements a DMA device with one DMA channel using a set
|
||||
* of mailbox channels provided by Broadcom SoC specific ring manager
|
||||
* driver. To exploit parallelism (as described above), all DMA request
|
||||
* coming to SBA RAID DMA channel are broken down to smaller requests
|
||||
* and submitted to multiple mailbox channels in round-robin fashion.
|
||||
* This driver implements a DMA device with one DMA channel using a single
|
||||
* mailbox channel provided by Broadcom SoC specific ring manager driver.
|
||||
* For having more SBA DMA channels, we can create more SBA device nodes
|
||||
* in Broadcom SoC specific DTS based on number of hardware rings supported
|
||||
* by Broadcom SoC ring manager.
|
||||
|
|
@ -85,6 +87,7 @@
|
|||
#define SBA_CMD_GALOIS 0xe
|
||||
|
||||
#define SBA_MAX_REQ_PER_MBOX_CHANNEL 8192
|
||||
#define SBA_MAX_MSG_SEND_PER_MBOX_CHANNEL 8
|
||||
|
||||
/* Driver helper macros */
|
||||
#define to_sba_request(tx) \
|
||||
|
|
@ -142,9 +145,7 @@ struct sba_device {
|
|||
u32 max_cmds_pool_size;
|
||||
/* Maibox client and Mailbox channels */
|
||||
struct mbox_client client;
|
||||
int mchans_count;
|
||||
atomic_t mchans_current;
|
||||
struct mbox_chan **mchans;
|
||||
struct mbox_chan *mchan;
|
||||
struct device *mbox_dev;
|
||||
/* DMA device and DMA channel */
|
||||
struct dma_device dma_dev;
|
||||
|
|
@ -200,14 +201,6 @@ static inline u32 __pure sba_cmd_pq_c_mdata(u32 d, u32 b1, u32 b0)
|
|||
|
||||
/* ====== General helper routines ===== */
|
||||
|
||||
static void sba_peek_mchans(struct sba_device *sba)
|
||||
{
|
||||
int mchan_idx;
|
||||
|
||||
for (mchan_idx = 0; mchan_idx < sba->mchans_count; mchan_idx++)
|
||||
mbox_client_peek_data(sba->mchans[mchan_idx]);
|
||||
}
|
||||
|
||||
static struct sba_request *sba_alloc_request(struct sba_device *sba)
|
||||
{
|
||||
bool found = false;
|
||||
|
|
@ -231,7 +224,7 @@ static struct sba_request *sba_alloc_request(struct sba_device *sba)
|
|||
* would have completed which will create more
|
||||
* room for new requests.
|
||||
*/
|
||||
sba_peek_mchans(sba);
|
||||
mbox_client_peek_data(sba->mchan);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -369,15 +362,11 @@ static void sba_cleanup_pending_requests(struct sba_device *sba)
|
|||
static int sba_send_mbox_request(struct sba_device *sba,
|
||||
struct sba_request *req)
|
||||
{
|
||||
int mchans_idx, ret = 0;
|
||||
|
||||
/* Select mailbox channel in round-robin fashion */
|
||||
mchans_idx = atomic_inc_return(&sba->mchans_current);
|
||||
mchans_idx = mchans_idx % sba->mchans_count;
|
||||
int ret = 0;
|
||||
|
||||
/* Send message for the request */
|
||||
req->msg.error = 0;
|
||||
ret = mbox_send_message(sba->mchans[mchans_idx], &req->msg);
|
||||
ret = mbox_send_message(sba->mchan, &req->msg);
|
||||
if (ret < 0) {
|
||||
dev_err(sba->dev, "send message failed with error %d", ret);
|
||||
return ret;
|
||||
|
|
@ -390,7 +379,7 @@ static int sba_send_mbox_request(struct sba_device *sba,
|
|||
}
|
||||
|
||||
/* Signal txdone for mailbox channel */
|
||||
mbox_client_txdone(sba->mchans[mchans_idx], ret);
|
||||
mbox_client_txdone(sba->mchan, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -402,13 +391,8 @@ static void _sba_process_pending_requests(struct sba_device *sba)
|
|||
u32 count;
|
||||
struct sba_request *req;
|
||||
|
||||
/*
|
||||
* Process few pending requests
|
||||
*
|
||||
* For now, we process (<number_of_mailbox_channels> * 8)
|
||||
* number of requests at a time.
|
||||
*/
|
||||
count = sba->mchans_count * 8;
|
||||
/* Process few pending requests */
|
||||
count = SBA_MAX_MSG_SEND_PER_MBOX_CHANNEL;
|
||||
while (!list_empty(&sba->reqs_pending_list) && count) {
|
||||
/* Get the first pending request */
|
||||
req = list_first_entry(&sba->reqs_pending_list,
|
||||
|
|
@ -442,7 +426,9 @@ static void sba_process_received_request(struct sba_device *sba,
|
|||
|
||||
WARN_ON(tx->cookie < 0);
|
||||
if (tx->cookie > 0) {
|
||||
spin_lock_irqsave(&sba->reqs_lock, flags);
|
||||
dma_cookie_complete(tx);
|
||||
spin_unlock_irqrestore(&sba->reqs_lock, flags);
|
||||
dmaengine_desc_get_callback_invoke(tx, NULL);
|
||||
dma_descriptor_unmap(tx);
|
||||
tx->callback = NULL;
|
||||
|
|
@ -570,7 +556,7 @@ static enum dma_status sba_tx_status(struct dma_chan *dchan,
|
|||
if (ret == DMA_COMPLETE)
|
||||
return ret;
|
||||
|
||||
sba_peek_mchans(sba);
|
||||
mbox_client_peek_data(sba->mchan);
|
||||
|
||||
return dma_cookie_status(dchan, cookie, txstate);
|
||||
}
|
||||
|
|
@ -1637,7 +1623,7 @@ static int sba_async_register(struct sba_device *sba)
|
|||
|
||||
static int sba_probe(struct platform_device *pdev)
|
||||
{
|
||||
int i, ret = 0, mchans_count;
|
||||
int ret = 0;
|
||||
struct sba_device *sba;
|
||||
struct platform_device *mbox_pdev;
|
||||
struct of_phandle_args args;
|
||||
|
|
@ -1650,12 +1636,11 @@ static int sba_probe(struct platform_device *pdev)
|
|||
sba->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, sba);
|
||||
|
||||
/* Number of channels equals number of mailbox channels */
|
||||
/* Number of mailbox channels should be atleast 1 */
|
||||
ret = of_count_phandle_with_args(pdev->dev.of_node,
|
||||
"mboxes", "#mbox-cells");
|
||||
if (ret <= 0)
|
||||
return -ENODEV;
|
||||
mchans_count = ret;
|
||||
|
||||
/* Determine SBA version from DT compatible string */
|
||||
if (of_device_is_compatible(sba->dev->of_node, "brcm,iproc-sba"))
|
||||
|
|
@ -1688,7 +1673,7 @@ static int sba_probe(struct platform_device *pdev)
|
|||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
sba->max_req = SBA_MAX_REQ_PER_MBOX_CHANNEL * mchans_count;
|
||||
sba->max_req = SBA_MAX_REQ_PER_MBOX_CHANNEL;
|
||||
sba->max_cmd_per_req = sba->max_pq_srcs + 3;
|
||||
sba->max_xor_srcs = sba->max_cmd_per_req - 1;
|
||||
sba->max_resp_pool_size = sba->max_req * sba->hw_resp_size;
|
||||
|
|
@ -1702,55 +1687,30 @@ static int sba_probe(struct platform_device *pdev)
|
|||
sba->client.knows_txdone = true;
|
||||
sba->client.tx_tout = 0;
|
||||
|
||||
/* Allocate mailbox channel array */
|
||||
sba->mchans = devm_kcalloc(&pdev->dev, mchans_count,
|
||||
sizeof(*sba->mchans), GFP_KERNEL);
|
||||
if (!sba->mchans)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Request mailbox channels */
|
||||
sba->mchans_count = 0;
|
||||
for (i = 0; i < mchans_count; i++) {
|
||||
sba->mchans[i] = mbox_request_channel(&sba->client, i);
|
||||
if (IS_ERR(sba->mchans[i])) {
|
||||
ret = PTR_ERR(sba->mchans[i]);
|
||||
goto fail_free_mchans;
|
||||
}
|
||||
sba->mchans_count++;
|
||||
/* Request mailbox channel */
|
||||
sba->mchan = mbox_request_channel(&sba->client, 0);
|
||||
if (IS_ERR(sba->mchan)) {
|
||||
ret = PTR_ERR(sba->mchan);
|
||||
goto fail_free_mchan;
|
||||
}
|
||||
atomic_set(&sba->mchans_current, 0);
|
||||
|
||||
/* Find-out underlying mailbox device */
|
||||
ret = of_parse_phandle_with_args(pdev->dev.of_node,
|
||||
"mboxes", "#mbox-cells", 0, &args);
|
||||
if (ret)
|
||||
goto fail_free_mchans;
|
||||
goto fail_free_mchan;
|
||||
mbox_pdev = of_find_device_by_node(args.np);
|
||||
of_node_put(args.np);
|
||||
if (!mbox_pdev) {
|
||||
ret = -ENODEV;
|
||||
goto fail_free_mchans;
|
||||
goto fail_free_mchan;
|
||||
}
|
||||
sba->mbox_dev = &mbox_pdev->dev;
|
||||
|
||||
/* All mailbox channels should be of same ring manager device */
|
||||
for (i = 1; i < mchans_count; i++) {
|
||||
ret = of_parse_phandle_with_args(pdev->dev.of_node,
|
||||
"mboxes", "#mbox-cells", i, &args);
|
||||
if (ret)
|
||||
goto fail_free_mchans;
|
||||
mbox_pdev = of_find_device_by_node(args.np);
|
||||
of_node_put(args.np);
|
||||
if (sba->mbox_dev != &mbox_pdev->dev) {
|
||||
ret = -EINVAL;
|
||||
goto fail_free_mchans;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prealloc channel resource */
|
||||
ret = sba_prealloc_channel_resources(sba);
|
||||
if (ret)
|
||||
goto fail_free_mchans;
|
||||
goto fail_free_mchan;
|
||||
|
||||
/* Check availability of debugfs */
|
||||
if (!debugfs_initialized())
|
||||
|
|
@ -1777,24 +1737,22 @@ skip_debugfs:
|
|||
goto fail_free_resources;
|
||||
|
||||
/* Print device info */
|
||||
dev_info(sba->dev, "%s using SBAv%d and %d mailbox channels",
|
||||
dev_info(sba->dev, "%s using SBAv%d mailbox channel from %s",
|
||||
dma_chan_name(&sba->dma_chan), sba->ver+1,
|
||||
sba->mchans_count);
|
||||
dev_name(sba->mbox_dev));
|
||||
|
||||
return 0;
|
||||
|
||||
fail_free_resources:
|
||||
debugfs_remove_recursive(sba->root);
|
||||
sba_freeup_channel_resources(sba);
|
||||
fail_free_mchans:
|
||||
for (i = 0; i < sba->mchans_count; i++)
|
||||
mbox_free_channel(sba->mchans[i]);
|
||||
fail_free_mchan:
|
||||
mbox_free_channel(sba->mchan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sba_remove(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
struct sba_device *sba = platform_get_drvdata(pdev);
|
||||
|
||||
dma_async_device_unregister(&sba->dma_dev);
|
||||
|
|
@ -1803,8 +1761,7 @@ static int sba_remove(struct platform_device *pdev)
|
|||
|
||||
sba_freeup_channel_resources(sba);
|
||||
|
||||
for (i = 0; i < sba->mchans_count; i++)
|
||||
mbox_free_channel(sba->mchans[i]);
|
||||
mbox_free_channel(sba->mchan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1319,8 +1319,8 @@ static void coh901318_list_print(struct coh901318_chan *cohc,
|
|||
int i = 0;
|
||||
|
||||
while (l) {
|
||||
dev_vdbg(COHC_2_DEV(cohc), "i %d, lli %p, ctrl 0x%x, src 0x%pad"
|
||||
", dst 0x%pad, link 0x%pad virt_link_addr 0x%p\n",
|
||||
dev_vdbg(COHC_2_DEV(cohc), "i %d, lli %p, ctrl 0x%x, src %pad"
|
||||
", dst %pad, link %pad virt_link_addr 0x%p\n",
|
||||
i, l, l->control, &l->src_addr, &l->dst_addr,
|
||||
&l->link_addr, l->virt_link_addr);
|
||||
i++;
|
||||
|
|
@ -2231,7 +2231,7 @@ coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
|
|||
spin_lock_irqsave(&cohc->lock, flg);
|
||||
|
||||
dev_vdbg(COHC_2_DEV(cohc),
|
||||
"[%s] channel %d src 0x%pad dest 0x%pad size %zu\n",
|
||||
"[%s] channel %d src %pad dest %pad size %zu\n",
|
||||
__func__, cohc->id, &src, &dest, size);
|
||||
|
||||
if (flags & DMA_PREP_INTERRUPT)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@
|
|||
|
||||
#define AXI_DMAC_FLAG_CYCLIC BIT(0)
|
||||
|
||||
/* The maximum ID allocated by the hardware is 31 */
|
||||
#define AXI_DMAC_SG_UNUSED 32U
|
||||
|
||||
struct axi_dmac_sg {
|
||||
dma_addr_t src_addr;
|
||||
dma_addr_t dest_addr;
|
||||
|
|
@ -80,6 +83,7 @@ struct axi_dmac_sg {
|
|||
unsigned int dest_stride;
|
||||
unsigned int src_stride;
|
||||
unsigned int id;
|
||||
bool schedule_when_free;
|
||||
};
|
||||
|
||||
struct axi_dmac_desc {
|
||||
|
|
@ -200,11 +204,21 @@ static void axi_dmac_start_transfer(struct axi_dmac_chan *chan)
|
|||
}
|
||||
sg = &desc->sg[desc->num_submitted];
|
||||
|
||||
/* Already queued in cyclic mode. Wait for it to finish */
|
||||
if (sg->id != AXI_DMAC_SG_UNUSED) {
|
||||
sg->schedule_when_free = true;
|
||||
return;
|
||||
}
|
||||
|
||||
desc->num_submitted++;
|
||||
if (desc->num_submitted == desc->num_sgs)
|
||||
chan->next_desc = NULL;
|
||||
else
|
||||
if (desc->num_submitted == desc->num_sgs) {
|
||||
if (desc->cyclic)
|
||||
desc->num_submitted = 0; /* Start again */
|
||||
else
|
||||
chan->next_desc = NULL;
|
||||
} else {
|
||||
chan->next_desc = desc;
|
||||
}
|
||||
|
||||
sg->id = axi_dmac_read(dmac, AXI_DMAC_REG_TRANSFER_ID);
|
||||
|
||||
|
|
@ -220,9 +234,11 @@ static void axi_dmac_start_transfer(struct axi_dmac_chan *chan)
|
|||
|
||||
/*
|
||||
* If the hardware supports cyclic transfers and there is no callback to
|
||||
* call, enable hw cyclic mode to avoid unnecessary interrupts.
|
||||
* call and only a single segment, enable hw cyclic mode to avoid
|
||||
* unnecessary interrupts.
|
||||
*/
|
||||
if (chan->hw_cyclic && desc->cyclic && !desc->vdesc.tx.callback)
|
||||
if (chan->hw_cyclic && desc->cyclic && !desc->vdesc.tx.callback &&
|
||||
desc->num_sgs == 1)
|
||||
flags |= AXI_DMAC_FLAG_CYCLIC;
|
||||
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, sg->x_len - 1);
|
||||
|
|
@ -237,37 +253,52 @@ static struct axi_dmac_desc *axi_dmac_active_desc(struct axi_dmac_chan *chan)
|
|||
struct axi_dmac_desc, vdesc.node);
|
||||
}
|
||||
|
||||
static void axi_dmac_transfer_done(struct axi_dmac_chan *chan,
|
||||
static bool axi_dmac_transfer_done(struct axi_dmac_chan *chan,
|
||||
unsigned int completed_transfers)
|
||||
{
|
||||
struct axi_dmac_desc *active;
|
||||
struct axi_dmac_sg *sg;
|
||||
bool start_next = false;
|
||||
|
||||
active = axi_dmac_active_desc(chan);
|
||||
if (!active)
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (active->cyclic) {
|
||||
vchan_cyclic_callback(&active->vdesc);
|
||||
} else {
|
||||
do {
|
||||
sg = &active->sg[active->num_completed];
|
||||
if (!(BIT(sg->id) & completed_transfers))
|
||||
break;
|
||||
active->num_completed++;
|
||||
if (active->num_completed == active->num_sgs) {
|
||||
do {
|
||||
sg = &active->sg[active->num_completed];
|
||||
if (sg->id == AXI_DMAC_SG_UNUSED) /* Not yet submitted */
|
||||
break;
|
||||
if (!(BIT(sg->id) & completed_transfers))
|
||||
break;
|
||||
active->num_completed++;
|
||||
sg->id = AXI_DMAC_SG_UNUSED;
|
||||
if (sg->schedule_when_free) {
|
||||
sg->schedule_when_free = false;
|
||||
start_next = true;
|
||||
}
|
||||
|
||||
if (active->cyclic)
|
||||
vchan_cyclic_callback(&active->vdesc);
|
||||
|
||||
if (active->num_completed == active->num_sgs) {
|
||||
if (active->cyclic) {
|
||||
active->num_completed = 0; /* wrap around */
|
||||
} else {
|
||||
list_del(&active->vdesc.node);
|
||||
vchan_cookie_complete(&active->vdesc);
|
||||
active = axi_dmac_active_desc(chan);
|
||||
}
|
||||
} while (active);
|
||||
}
|
||||
}
|
||||
} while (active);
|
||||
|
||||
return start_next;
|
||||
}
|
||||
|
||||
static irqreturn_t axi_dmac_interrupt_handler(int irq, void *devid)
|
||||
{
|
||||
struct axi_dmac *dmac = devid;
|
||||
unsigned int pending;
|
||||
bool start_next = false;
|
||||
|
||||
pending = axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING);
|
||||
if (!pending)
|
||||
|
|
@ -281,10 +312,10 @@ static irqreturn_t axi_dmac_interrupt_handler(int irq, void *devid)
|
|||
unsigned int completed;
|
||||
|
||||
completed = axi_dmac_read(dmac, AXI_DMAC_REG_TRANSFER_DONE);
|
||||
axi_dmac_transfer_done(&dmac->chan, completed);
|
||||
start_next = axi_dmac_transfer_done(&dmac->chan, completed);
|
||||
}
|
||||
/* Space has become available in the descriptor queue */
|
||||
if (pending & AXI_DMAC_IRQ_SOT)
|
||||
if ((pending & AXI_DMAC_IRQ_SOT) || start_next)
|
||||
axi_dmac_start_transfer(&dmac->chan);
|
||||
spin_unlock(&dmac->chan.vchan.lock);
|
||||
|
||||
|
|
@ -334,12 +365,16 @@ static void axi_dmac_issue_pending(struct dma_chan *c)
|
|||
static struct axi_dmac_desc *axi_dmac_alloc_desc(unsigned int num_sgs)
|
||||
{
|
||||
struct axi_dmac_desc *desc;
|
||||
unsigned int i;
|
||||
|
||||
desc = kzalloc(sizeof(struct axi_dmac_desc) +
|
||||
sizeof(struct axi_dmac_sg) * num_sgs, GFP_NOWAIT);
|
||||
if (!desc)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < num_sgs; i++)
|
||||
desc->sg[i].id = AXI_DMAC_SG_UNUSED;
|
||||
|
||||
desc->num_sgs = num_sgs;
|
||||
|
||||
return desc;
|
||||
|
|
|
|||
|
|
@ -702,6 +702,7 @@ static int dmatest_func(void *data)
|
|||
* free it this time?" dancing. For now, just
|
||||
* leave it dangling.
|
||||
*/
|
||||
WARN(1, "dmatest: Kernel stack may be corrupted!!\n");
|
||||
dmaengine_unmap_put(um);
|
||||
result("test timed out", total_tests, src_off, dst_off,
|
||||
len, 0);
|
||||
|
|
|
|||
|
|
@ -891,6 +891,10 @@ static int edma_slave_config(struct dma_chan *chan,
|
|||
cfg->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
|
||||
return -EINVAL;
|
||||
|
||||
if (cfg->src_maxburst > chan->device->max_burst ||
|
||||
cfg->dst_maxburst > chan->device->max_burst)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(&echan->cfg, cfg, sizeof(echan->cfg));
|
||||
|
||||
return 0;
|
||||
|
|
@ -1868,6 +1872,7 @@ static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode)
|
|||
s_ddev->dst_addr_widths = EDMA_DMA_BUSWIDTHS;
|
||||
s_ddev->directions |= (BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV));
|
||||
s_ddev->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
|
||||
s_ddev->max_burst = SZ_32K - 1; /* CIDX: 16bit signed */
|
||||
|
||||
s_ddev->dev = ecc->dev;
|
||||
INIT_LIST_HEAD(&s_ddev->channels);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/of_device.h>
|
||||
#include <linux/of_dma.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
|
@ -730,14 +731,23 @@ static int mdc_slave_config(struct dma_chan *chan,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mdc_alloc_chan_resources(struct dma_chan *chan)
|
||||
{
|
||||
struct mdc_chan *mchan = to_mdc_chan(chan);
|
||||
struct device *dev = mdma2dev(mchan->mdma);
|
||||
|
||||
return pm_runtime_get_sync(dev);
|
||||
}
|
||||
|
||||
static void mdc_free_chan_resources(struct dma_chan *chan)
|
||||
{
|
||||
struct mdc_chan *mchan = to_mdc_chan(chan);
|
||||
struct mdc_dma *mdma = mchan->mdma;
|
||||
struct device *dev = mdma2dev(mdma);
|
||||
|
||||
mdc_terminate_all(chan);
|
||||
|
||||
mdma->soc->disable_chan(mchan);
|
||||
pm_runtime_put(dev);
|
||||
}
|
||||
|
||||
static irqreturn_t mdc_chan_irq(int irq, void *dev_id)
|
||||
|
|
@ -854,6 +864,22 @@ static const struct of_device_id mdc_dma_of_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, mdc_dma_of_match);
|
||||
|
||||
static int img_mdc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct mdc_dma *mdma = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(mdma->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int img_mdc_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct mdc_dma *mdma = dev_get_drvdata(dev);
|
||||
|
||||
return clk_prepare_enable(mdma->clk);
|
||||
}
|
||||
|
||||
static int mdc_dma_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mdc_dma *mdma;
|
||||
|
|
@ -883,10 +909,6 @@ static int mdc_dma_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(mdma->clk))
|
||||
return PTR_ERR(mdma->clk);
|
||||
|
||||
ret = clk_prepare_enable(mdma->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dma_cap_zero(mdma->dma_dev.cap_mask);
|
||||
dma_cap_set(DMA_SLAVE, mdma->dma_dev.cap_mask);
|
||||
dma_cap_set(DMA_PRIVATE, mdma->dma_dev.cap_mask);
|
||||
|
|
@ -919,12 +941,13 @@ static int mdc_dma_probe(struct platform_device *pdev)
|
|||
"img,max-burst-multiplier",
|
||||
&mdma->max_burst_mult);
|
||||
if (ret)
|
||||
goto disable_clk;
|
||||
return ret;
|
||||
|
||||
mdma->dma_dev.dev = &pdev->dev;
|
||||
mdma->dma_dev.device_prep_slave_sg = mdc_prep_slave_sg;
|
||||
mdma->dma_dev.device_prep_dma_cyclic = mdc_prep_dma_cyclic;
|
||||
mdma->dma_dev.device_prep_dma_memcpy = mdc_prep_dma_memcpy;
|
||||
mdma->dma_dev.device_alloc_chan_resources = mdc_alloc_chan_resources;
|
||||
mdma->dma_dev.device_free_chan_resources = mdc_free_chan_resources;
|
||||
mdma->dma_dev.device_tx_status = mdc_tx_status;
|
||||
mdma->dma_dev.device_issue_pending = mdc_issue_pending;
|
||||
|
|
@ -945,15 +968,14 @@ static int mdc_dma_probe(struct platform_device *pdev)
|
|||
mchan->mdma = mdma;
|
||||
mchan->chan_nr = i;
|
||||
mchan->irq = platform_get_irq(pdev, i);
|
||||
if (mchan->irq < 0) {
|
||||
ret = mchan->irq;
|
||||
goto disable_clk;
|
||||
}
|
||||
if (mchan->irq < 0)
|
||||
return mchan->irq;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, mchan->irq, mdc_chan_irq,
|
||||
IRQ_TYPE_LEVEL_HIGH,
|
||||
dev_name(&pdev->dev), mchan);
|
||||
if (ret < 0)
|
||||
goto disable_clk;
|
||||
return ret;
|
||||
|
||||
mchan->vc.desc_free = mdc_desc_free;
|
||||
vchan_init(&mchan->vc, &mdma->dma_dev);
|
||||
|
|
@ -962,14 +984,19 @@ static int mdc_dma_probe(struct platform_device *pdev)
|
|||
mdma->desc_pool = dmam_pool_create(dev_name(&pdev->dev), &pdev->dev,
|
||||
sizeof(struct mdc_hw_list_desc),
|
||||
4, 0);
|
||||
if (!mdma->desc_pool) {
|
||||
ret = -ENOMEM;
|
||||
goto disable_clk;
|
||||
if (!mdma->desc_pool)
|
||||
return -ENOMEM;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
if (!pm_runtime_enabled(&pdev->dev)) {
|
||||
ret = img_mdc_runtime_resume(&pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dma_async_device_register(&mdma->dma_dev);
|
||||
if (ret)
|
||||
goto disable_clk;
|
||||
goto suspend;
|
||||
|
||||
ret = of_dma_controller_register(pdev->dev.of_node, mdc_of_xlate, mdma);
|
||||
if (ret)
|
||||
|
|
@ -982,8 +1009,10 @@ static int mdc_dma_probe(struct platform_device *pdev)
|
|||
|
||||
unregister:
|
||||
dma_async_device_unregister(&mdma->dma_dev);
|
||||
disable_clk:
|
||||
clk_disable_unprepare(mdma->clk);
|
||||
suspend:
|
||||
if (!pm_runtime_enabled(&pdev->dev))
|
||||
img_mdc_runtime_suspend(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1004,14 +1033,47 @@ static int mdc_dma_remove(struct platform_device *pdev)
|
|||
tasklet_kill(&mchan->vc.task);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(mdma->clk);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (!pm_runtime_status_suspended(&pdev->dev))
|
||||
img_mdc_runtime_suspend(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int img_mdc_suspend_late(struct device *dev)
|
||||
{
|
||||
struct mdc_dma *mdma = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
/* Check that all channels are idle */
|
||||
for (i = 0; i < mdma->nr_channels; i++) {
|
||||
struct mdc_chan *mchan = &mdma->channels[i];
|
||||
|
||||
if (unlikely(mchan->desc))
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return pm_runtime_force_suspend(dev);
|
||||
}
|
||||
|
||||
static int img_mdc_resume_early(struct device *dev)
|
||||
{
|
||||
return pm_runtime_force_resume(dev);
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static const struct dev_pm_ops img_mdc_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(img_mdc_runtime_suspend,
|
||||
img_mdc_runtime_resume, NULL)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(img_mdc_suspend_late,
|
||||
img_mdc_resume_early)
|
||||
};
|
||||
|
||||
static struct platform_driver mdc_dma_driver = {
|
||||
.driver = {
|
||||
.name = "img-mdc-dma",
|
||||
.pm = &img_mdc_pm_ops,
|
||||
.of_match_table = of_match_ptr(mdc_dma_of_match),
|
||||
},
|
||||
.probe = mdc_dma_probe,
|
||||
|
|
|
|||
|
|
@ -364,9 +364,9 @@ static void imxdma_disable_hw(struct imxdma_channel *imxdmac)
|
|||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void imxdma_watchdog(unsigned long data)
|
||||
static void imxdma_watchdog(struct timer_list *t)
|
||||
{
|
||||
struct imxdma_channel *imxdmac = (struct imxdma_channel *)data;
|
||||
struct imxdma_channel *imxdmac = from_timer(imxdmac, t, watchdog);
|
||||
struct imxdma_engine *imxdma = imxdmac->imxdma;
|
||||
int channel = imxdmac->channel;
|
||||
|
||||
|
|
@ -1153,9 +1153,7 @@ static int __init imxdma_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
imxdmac->irq = irq + i;
|
||||
init_timer(&imxdmac->watchdog);
|
||||
imxdmac->watchdog.function = &imxdma_watchdog;
|
||||
imxdmac->watchdog.data = (unsigned long)imxdmac;
|
||||
timer_setup(&imxdmac->watchdog, imxdma_watchdog, 0);
|
||||
}
|
||||
|
||||
imxdmac->imxdma = imxdma;
|
||||
|
|
|
|||
|
|
@ -178,6 +178,14 @@
|
|||
#define SDMA_WATERMARK_LEVEL_HWE BIT(29)
|
||||
#define SDMA_WATERMARK_LEVEL_CONT BIT(31)
|
||||
|
||||
#define SDMA_DMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
|
||||
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
|
||||
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
|
||||
|
||||
#define SDMA_DMA_DIRECTIONS (BIT(DMA_DEV_TO_MEM) | \
|
||||
BIT(DMA_MEM_TO_DEV) | \
|
||||
BIT(DMA_DEV_TO_DEV))
|
||||
|
||||
/*
|
||||
* Mode/Count of data node descriptors - IPCv2
|
||||
*/
|
||||
|
|
@ -1851,9 +1859,9 @@ static int sdma_probe(struct platform_device *pdev)
|
|||
sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic;
|
||||
sdma->dma_device.device_config = sdma_config;
|
||||
sdma->dma_device.device_terminate_all = sdma_disable_channel_with_delay;
|
||||
sdma->dma_device.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
|
||||
sdma->dma_device.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
|
||||
sdma->dma_device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
|
||||
sdma->dma_device.src_addr_widths = SDMA_DMA_BUSWIDTHS;
|
||||
sdma->dma_device.dst_addr_widths = SDMA_DMA_BUSWIDTHS;
|
||||
sdma->dma_device.directions = SDMA_DMA_DIRECTIONS;
|
||||
sdma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
|
||||
sdma->dma_device.device_issue_pending = sdma_issue_pending;
|
||||
sdma->dma_device.dev->dma_parms = &sdma->dma_parms;
|
||||
|
|
|
|||
|
|
@ -474,7 +474,7 @@ int ioat_check_space_lock(struct ioatdma_chan *ioat_chan, int num_descs)
|
|||
if (time_is_before_jiffies(ioat_chan->timer.expires)
|
||||
&& timer_pending(&ioat_chan->timer)) {
|
||||
mod_timer(&ioat_chan->timer, jiffies + COMPLETION_TIMEOUT);
|
||||
ioat_timer_event((unsigned long)ioat_chan);
|
||||
ioat_timer_event(&ioat_chan->timer);
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
|
|
@ -862,9 +862,9 @@ static void check_active(struct ioatdma_chan *ioat_chan)
|
|||
mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT);
|
||||
}
|
||||
|
||||
void ioat_timer_event(unsigned long data)
|
||||
void ioat_timer_event(struct timer_list *t)
|
||||
{
|
||||
struct ioatdma_chan *ioat_chan = to_ioat_chan((void *)data);
|
||||
struct ioatdma_chan *ioat_chan = from_timer(ioat_chan, t, timer);
|
||||
dma_addr_t phys_complete;
|
||||
u64 status;
|
||||
|
||||
|
|
|
|||
|
|
@ -406,10 +406,9 @@ enum dma_status
|
|||
ioat_tx_status(struct dma_chan *c, dma_cookie_t cookie,
|
||||
struct dma_tx_state *txstate);
|
||||
void ioat_cleanup_event(unsigned long data);
|
||||
void ioat_timer_event(unsigned long data);
|
||||
void ioat_timer_event(struct timer_list *t);
|
||||
int ioat_check_space_lock(struct ioatdma_chan *ioat_chan, int num_descs);
|
||||
void ioat_issue_pending(struct dma_chan *chan);
|
||||
void ioat_timer_event(unsigned long data);
|
||||
|
||||
/* IOAT Init functions */
|
||||
bool is_bwd_ioat(struct pci_dev *pdev);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue