提交 d6a4c0e5 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma

Pull slave-dmaengine updates from Vinod Koul:

 - new drivers for:
        - Ingenic JZ4780 controller
        - APM X-Gene controller
        - Freescale RaidEngine device
        - Renesas USB Controller

  - remove device_alloc_chan_resources dummy handlers

  - sh driver cleanups for peri peri and related emmc and asoc patches
    as well

  - fixes and enhancements spread over the drivers

* 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma: (59 commits)
  dmaengine: dw: don't prompt for DW_DMAC_CORE
  dmaengine: shdmac: avoid unused variable warnings
  dmaengine: fix platform_no_drv_owner.cocci warnings
  dmaengine: pch_dma: fix memory leak on failure path in pch_dma_probe()
  dmaengine: at_xdmac: unlock spin lock before return
  dmaengine: xgene: devm_ioremap() returns NULL on error
  dmaengine: xgene: buffer overflow in xgene_dma_init_channels()
  dmaengine: usb-dmac: Fix dereferencing freed memory 'desc'
  dmaengine: sa11x0: report slave capabilities to upper layers
  dmaengine: vdma: Fix compilation warnings
  dmaengine: fsl_raid: statify fsl_re_chan_probe
  dmaengine: Driver support for FSL RaidEngine device.
  dmaengine: xgene_dma_init_ring_mngr() can be static
  Documentation: dma: Add documentation for the APM X-Gene SoC DMA device DTS binding
  arm64: dts: Add APM X-Gene SoC DMA device and DMA clock DTS nodes
  dmaengine: Add support for APM X-Gene SoC DMA engine driver
  dmaengine: usb-dmac: Add Renesas USB DMA Controller (USB-DMAC) driver
  dmaengine: renesas,usb-dmac: Add device tree bindings documentation
  dmaengine: edma: fixed wrongly initialized data parameter to the edma callback
  dmaengine: ste_dma40: fix implicit conversion
  ...
Applied Micro X-Gene SoC DMA nodes
DMA nodes are defined to describe on-chip DMA interfaces in
APM X-Gene SoC.
Required properties for DMA interfaces:
- compatible: Should be "apm,xgene-dma".
- device_type: set to "dma".
- reg: Address and length of the register set for the device.
It contains the information of registers in the following order:
1st - DMA control and status register address space.
2nd - Descriptor ring control and status register address space.
3rd - Descriptor ring command register address space.
4th - Soc efuse register address space.
- interrupts: DMA has 5 interrupts sources. 1st interrupt is
DMA error reporting interrupt. 2nd, 3rd, 4th and 5th interrupts
are completion interrupts for each DMA channels.
- clocks: Reference to the clock entry.
Optional properties:
- dma-coherent : Present if dma operations are coherent
Example:
dmaclk: dmaclk@1f27c000 {
compatible = "apm,xgene-device-clock";
#clock-cells = <1>;
clocks = <&socplldiv2 0>;
reg = <0x0 0x1f27c000 0x0 0x1000>;
reg-names = "csr-reg";
clock-output-names = "dmaclk";
};
dma: dma@1f270000 {
compatible = "apm,xgene-storm-dma";
device_type = "dma";
reg = <0x0 0x1f270000 0x0 0x10000>,
<0x0 0x1f200000 0x0 0x10000>,
<0x0 0x1b008000 0x0 0x2000>,
<0x0 0x1054a000 0x0 0x100>;
interrupts = <0x0 0x82 0x4>,
<0x0 0xb8 0x4>,
<0x0 0xb9 0x4>,
<0x0 0xba 0x4>,
<0x0 0xbb 0x4>;
dma-coherent;
clocks = <&dmaclk 0>;
};
* Ingenic JZ4780 DMA Controller
Required properties:
- compatible: Should be "ingenic,jz4780-dma"
- reg: Should contain the DMA controller registers location and length.
- interrupts: Should contain the interrupt specifier of the DMA controller.
- interrupt-parent: Should be the phandle of the interrupt controller that
- clocks: Should contain a clock specifier for the JZ4780 PDMA clock.
- #dma-cells: Must be <2>. Number of integer cells in the dmas property of
DMA clients (see below).
Optional properties:
- ingenic,reserved-channels: Bitmask of channels to reserve for devices that
need a specific channel. These channels will only be assigned when explicitly
requested by a client. The primary use for this is channels 0 and 1, which
can be configured to have special behaviour for NAND/BCH when using
programmable firmware.
Example:
dma: dma@13420000 {
compatible = "ingenic,jz4780-dma";
reg = <0x13420000 0x10000>;
interrupt-parent = <&intc>;
interrupts = <10>;
clocks = <&cgu JZ4780_CLK_PDMA>;
#dma-cells = <2>;
ingenic,reserved-channels = <0x3>;
};
DMA clients must use the format described in dma.txt, giving a phandle to the
DMA controller plus the following 2 integer cells:
1. Request type: The DMA request type for transfers to/from the device on
the allocated channel, as defined in the SoC documentation.
2. Channel: If set to 0xffffffff, any available channel will be allocated for
the client. Otherwise, the exact channel specified will be used. The channel
should be reserved on the DMA controller using the ingenic,reserved-channels
property.
Example:
uart0: serial@10030000 {
...
dmas = <&dma 0x14 0xffffffff
&dma 0x15 0xffffffff>;
dma-names = "tx", "rx";
...
};
...@@ -4,6 +4,7 @@ Required properties: ...@@ -4,6 +4,7 @@ Required properties:
- compatible: must be one of the following: - compatible: must be one of the following:
* "qcom,bam-v1.4.0" for MSM8974, APQ8074 and APQ8084 * "qcom,bam-v1.4.0" for MSM8974, APQ8074 and APQ8084
* "qcom,bam-v1.3.0" for APQ8064, IPQ8064 and MSM8960 * "qcom,bam-v1.3.0" for APQ8064, IPQ8064 and MSM8960
* "qcom,bam-v1.7.0" for MSM8916
- reg: Address range for DMA registers - reg: Address range for DMA registers
- interrupts: Should contain the one interrupt shared by all channels - interrupts: Should contain the one interrupt shared by all channels
- #dma-cells: must be <1>, the cell in the dmas property of the client device - #dma-cells: must be <1>, the cell in the dmas property of the client device
......
* R-Car Audio DMAC peri peri Device Tree bindings
Required properties:
- compatible: should be "renesas,rcar-audmapp"
- #dma-cells: should be <1>, see "dmas" property below
Example:
audmapp: audio-dma-pp@0xec740000 {
compatible = "renesas,rcar-audmapp";
#dma-cells = <1>;
reg = <0 0xec740000 0 0x200>;
};
* DMA client
Required properties:
- dmas: a list of <[DMA multiplexer phandle] [SRS << 8 | DRS]> pairs.
where SRS/DRS are specified in the SoC manual.
It will be written into PDMACHCR as high 16-bit parts.
- dma-names: a list of DMA channel names, one per "dmas" entry
Example:
dmas = <&audmapp 0x2d00
&audmapp 0x3700>;
dma-names = "src0_ssiu0",
"dvc0_ssiu0";
* Renesas USB DMA Controller Device Tree bindings
Required Properties:
- compatible: must contain "renesas,usb-dmac"
- reg: base address and length of the registers block for the DMAC
- interrupts: interrupt specifiers for the DMAC, one for each entry in
interrupt-names.
- interrupt-names: one entry per channel, named "ch%u", where %u is the
channel number ranging from zero to the number of channels minus one.
- clocks: a list of phandle + clock-specifier pairs.
- #dma-cells: must be <1>, the cell specifies the channel number of the DMAC
port connected to the DMA client.
- dma-channels: number of DMA channels
Example: R8A7790 (R-Car H2) USB-DMACs
usb_dmac0: dma-controller@e65a0000 {
compatible = "renesas,usb-dmac";
reg = <0 0xe65a0000 0 0x100>;
interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH
0 109 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "ch0", "ch1";
clocks = <&mstp3_clks R8A7790_CLK_USBDMAC0>;
#dma-cells = <1>;
dma-channels = <2>;
};
usb_dmac1: dma-controller@e65b0000 {
compatible = "renesas,usb-dmac";
reg = <0 0xe65b0000 0 0x100>;
interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH
0 110 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "ch0", "ch1";
clocks = <&mstp3_clks R8A7790_CLK_USBDMAC1>;
#dma-cells = <1>;
dma-channels = <2>;
};
...@@ -5009,6 +5009,11 @@ W: http://industrypack.sourceforge.net ...@@ -5009,6 +5009,11 @@ W: http://industrypack.sourceforge.net
S: Maintained S: Maintained
F: drivers/ipack/ F: drivers/ipack/
INGENIC JZ4780 DMA Driver
M: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
S: Maintained
F: drivers/dma/dma-jz4780.c
INTEGRITY MEASUREMENT ARCHITECTURE (IMA) INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
M: Mimi Zohar <zohar@linux.vnet.ibm.com> M: Mimi Zohar <zohar@linux.vnet.ibm.com>
M: Dmitry Kasatkin <dmitry.kasatkin@gmail.com> M: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
......
...@@ -754,12 +754,12 @@ static struct platform_device vcc_sdhi1 = { ...@@ -754,12 +754,12 @@ static struct platform_device vcc_sdhi1 = {
}; };
/* SDHI0 */ /* SDHI0 */
static struct sh_mobile_sdhi_info sdhi0_info = { static struct tmio_mmc_data sdhi0_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX,
.tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
MMC_CAP_POWER_OFF_CARD, MMC_CAP_POWER_OFF_CARD,
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD, .flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
.cd_gpio = 167, .cd_gpio = 167,
}; };
...@@ -796,12 +796,12 @@ static struct platform_device sdhi0_device = { ...@@ -796,12 +796,12 @@ static struct platform_device sdhi0_device = {
}; };
/* SDHI1 */ /* SDHI1 */
static struct sh_mobile_sdhi_info sdhi1_info = { static struct tmio_mmc_data sdhi1_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI1_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI1_RX,
.tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
MMC_CAP_POWER_OFF_CARD, MMC_CAP_POWER_OFF_CARD,
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD, .flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
/* Port72 cannot generate IRQs, will be used in polling mode. */ /* Port72 cannot generate IRQs, will be used in polling mode. */
.cd_gpio = 72, .cd_gpio = 72,
}; };
......
...@@ -201,12 +201,12 @@ static struct rcar_phy_platform_data usb_phy_platform_data __initdata = ...@@ -201,12 +201,12 @@ static struct rcar_phy_platform_data usb_phy_platform_data __initdata =
/* SDHI */ /* SDHI */
static struct sh_mobile_sdhi_info sdhi0_info __initdata = { static struct tmio_mmc_data sdhi0_info __initdata = {
.dma_slave_tx = HPBDMA_SLAVE_SDHI0_TX, .chan_priv_tx = (void *)HPBDMA_SLAVE_SDHI0_TX,
.dma_slave_rx = HPBDMA_SLAVE_SDHI0_RX, .chan_priv_rx = (void *)HPBDMA_SLAVE_SDHI0_RX,
.tmio_caps = MMC_CAP_SD_HIGHSPEED, .capabilities = MMC_CAP_SD_HIGHSPEED,
.tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, .ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, .flags = TMIO_MMC_HAS_IDLE_WAIT,
}; };
static struct resource sdhi0_resources[] __initdata = { static struct resource sdhi0_resources[] __initdata = {
...@@ -683,7 +683,7 @@ static void __init bockw_init(void) ...@@ -683,7 +683,7 @@ static void __init bockw_init(void)
platform_device_register_resndata( platform_device_register_resndata(
NULL, "sh_mobile_sdhi", 0, NULL, "sh_mobile_sdhi", 0,
sdhi0_resources, ARRAY_SIZE(sdhi0_resources), sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_info, sizeof(struct sh_mobile_sdhi_info)); &sdhi0_info, sizeof(struct tmio_mmc_data));
} }
/* for Audio */ /* for Audio */
......
...@@ -442,11 +442,11 @@ static struct platform_device vcc_sdhi2 = { ...@@ -442,11 +442,11 @@ static struct platform_device vcc_sdhi2 = {
}; };
/* SDHI */ /* SDHI */
static struct sh_mobile_sdhi_info sdhi0_info = { static struct tmio_mmc_data sdhi0_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX,
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, .flags = TMIO_MMC_HAS_IDLE_WAIT,
.tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
MMC_CAP_POWER_OFF_CARD, MMC_CAP_POWER_OFF_CARD,
}; };
...@@ -484,13 +484,13 @@ static struct platform_device sdhi0_device = { ...@@ -484,13 +484,13 @@ static struct platform_device sdhi0_device = {
}; };
/* Micro SD */ /* Micro SD */
static struct sh_mobile_sdhi_info sdhi2_info = { static struct tmio_mmc_data sdhi2_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI2_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI2_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI2_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI2_RX,
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | .flags = TMIO_MMC_HAS_IDLE_WAIT |
TMIO_MMC_USE_GPIO_CD | TMIO_MMC_USE_GPIO_CD |
TMIO_MMC_WRPROTECT_DISABLE, TMIO_MMC_WRPROTECT_DISABLE,
.tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_POWER_OFF_CARD, .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_POWER_OFF_CARD,
.cd_gpio = 13, .cd_gpio = 13,
}; };
......
...@@ -122,11 +122,11 @@ static struct resource sdhi0_resources[] = { ...@@ -122,11 +122,11 @@ static struct resource sdhi0_resources[] = {
}, },
}; };
static struct sh_mobile_sdhi_info sdhi0_platform_data = { static struct tmio_mmc_data sdhi0_platform_data = {
.dma_slave_tx = HPBDMA_SLAVE_SDHI0_TX, .chan_priv_tx = (void *)HPBDMA_SLAVE_SDHI0_TX,
.dma_slave_rx = HPBDMA_SLAVE_SDHI0_RX, .chan_priv_rx = (void *)HPBDMA_SLAVE_SDHI0_RX,
.tmio_flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT, .flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
.tmio_caps = MMC_CAP_SD_HIGHSPEED, .capabilities = MMC_CAP_SD_HIGHSPEED,
}; };
static struct platform_device sdhi0_device = { static struct platform_device sdhi0_device = {
......
...@@ -102,6 +102,7 @@ ...@@ -102,6 +102,7 @@
#address-cells = <2>; #address-cells = <2>;
#size-cells = <2>; #size-cells = <2>;
ranges; ranges;
dma-ranges = <0x0 0x0 0x0 0x0 0x400 0x0>;
clocks { clocks {
#address-cells = <2>; #address-cells = <2>;
...@@ -362,6 +363,15 @@ ...@@ -362,6 +363,15 @@
reg-names = "csr-reg"; reg-names = "csr-reg";
clock-output-names = "pcie4clk"; clock-output-names = "pcie4clk";
}; };
dmaclk: dmaclk@1f27c000 {
compatible = "apm,xgene-device-clock";
#clock-cells = <1>;
clocks = <&socplldiv2 0>;
reg = <0x0 0x1f27c000 0x0 0x1000>;
reg-names = "csr-reg";
clock-output-names = "dmaclk";
};
}; };
pcie0: pcie@1f2b0000 { pcie0: pcie@1f2b0000 {
...@@ -684,5 +694,21 @@ ...@@ -684,5 +694,21 @@
interrupts = <0x0 0x41 0x4>; interrupts = <0x0 0x41 0x4>;
clocks = <&rngpkaclk 0>; clocks = <&rngpkaclk 0>;
}; };
dma: dma@1f270000 {
compatible = "apm,xgene-storm-dma";
device_type = "dma";
reg = <0x0 0x1f270000 0x0 0x10000>,
<0x0 0x1f200000 0x0 0x10000>,
<0x0 0x1b008000 0x0 0x2000>,
<0x0 0x1054a000 0x0 0x100>;
interrupts = <0x0 0x82 0x4>,
<0x0 0xb8 0x4>,
<0x0 0xb9 0x4>,
<0x0 0xba 0x4>,
<0x0 0xbb 0x4>;
dma-coherent;
clocks = <&dmaclk 0>;
};
}; };
}; };
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/flash.h> #include <linux/spi/flash.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/sh_mmcif.h> #include <linux/mmc/sh_mmcif.h>
#include <linux/mmc/sh_mobile_sdhi.h> #include <linux/mmc/sh_mobile_sdhi.h>
...@@ -243,10 +244,10 @@ static struct platform_device sh_mmcif_device = { ...@@ -243,10 +244,10 @@ static struct platform_device sh_mmcif_device = {
}; };
/* SDHI0 */ /* SDHI0 */
static struct sh_mobile_sdhi_info sdhi_info = { static struct tmio_mmc_data sdhi_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI_RX,
.tmio_caps = MMC_CAP_SD_HIGHSPEED, .capabilities = MMC_CAP_SD_HIGHSPEED,
}; };
static struct resource sdhi_resources[] = { static struct resource sdhi_resources[] = {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/mmc/sh_mobile_sdhi.h> #include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/mtd/sh_flctl.h> #include <linux/mtd/sh_flctl.h>
#include <linux/mfd/tmio.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
...@@ -447,8 +448,8 @@ static struct resource sdhi0_cn3_resources[] = { ...@@ -447,8 +448,8 @@ static struct resource sdhi0_cn3_resources[] = {
}, },
}; };
static struct sh_mobile_sdhi_info sdhi0_cn3_data = { static struct tmio_mmc_data sdhi0_cn3_data = {
.tmio_caps = MMC_CAP_SDIO_IRQ, .capabilities = MMC_CAP_SDIO_IRQ,
}; };
static struct platform_device sdhi0_cn3_device = { static struct platform_device sdhi0_cn3_device = {
...@@ -474,8 +475,8 @@ static struct resource sdhi1_cn7_resources[] = { ...@@ -474,8 +475,8 @@ static struct resource sdhi1_cn7_resources[] = {
}, },
}; };
static struct sh_mobile_sdhi_info sdhi1_cn7_data = { static struct tmio_mmc_data sdhi1_cn7_data = {
.tmio_caps = MMC_CAP_SDIO_IRQ, .capabilities = MMC_CAP_SDIO_IRQ,
}; };
static struct platform_device sdhi1_cn7_device = { static struct platform_device sdhi1_cn7_device = {
......
...@@ -601,12 +601,12 @@ static struct platform_device sdhi0_power = { ...@@ -601,12 +601,12 @@ static struct platform_device sdhi0_power = {
}, },
}; };
static struct sh_mobile_sdhi_info sdhi0_info = { static struct tmio_mmc_data sdhi0_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX,
.tmio_caps = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD | .capabilities = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
MMC_CAP_NEEDS_POLL, MMC_CAP_NEEDS_POLL,
.tmio_flags = TMIO_MMC_USE_GPIO_CD, .flags = TMIO_MMC_USE_GPIO_CD,
.cd_gpio = GPIO_PTY7, .cd_gpio = GPIO_PTY7,
}; };
...@@ -635,12 +635,12 @@ static struct platform_device sdhi0_device = { ...@@ -635,12 +635,12 @@ static struct platform_device sdhi0_device = {
#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
/* SDHI1 */ /* SDHI1 */
static struct sh_mobile_sdhi_info sdhi1_info = { static struct tmio_mmc_data sdhi1_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI1_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI1_RX,
.tmio_caps = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD | .capabilities = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
MMC_CAP_NEEDS_POLL, MMC_CAP_NEEDS_POLL,
.tmio_flags = TMIO_MMC_USE_GPIO_CD, .flags = TMIO_MMC_USE_GPIO_CD,
.cd_gpio = GPIO_PTW7, .cd_gpio = GPIO_PTW7,
}; };
......
...@@ -373,11 +373,11 @@ static struct resource kfr2r09_sh_sdhi0_resources[] = { ...@@ -373,11 +373,11 @@ static struct resource kfr2r09_sh_sdhi0_resources[] = {
}, },
}; };
static struct sh_mobile_sdhi_info sh7724_sdhi0_data = { static struct tmio_mmc_data sh7724_sdhi0_data = {
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX,
.tmio_flags = TMIO_MMC_WRPROTECT_DISABLE, .flags = TMIO_MMC_WRPROTECT_DISABLE,
.tmio_caps = MMC_CAP_SDIO_IRQ, .capabilities = MMC_CAP_SDIO_IRQ,
}; };
static struct platform_device kfr2r09_sh_sdhi0_device = { static struct platform_device kfr2r09_sh_sdhi0_device = {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/sh_mobile_sdhi.h> #include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/mfd/tmio.h>
#include <linux/mtd/nand.h> #include <linux/mtd/nand.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
...@@ -408,10 +409,10 @@ static struct resource sdhi_cn9_resources[] = { ...@@ -408,10 +409,10 @@ static struct resource sdhi_cn9_resources[] = {
}, },
}; };
static struct sh_mobile_sdhi_info sh7724_sdhi_data = { static struct tmio_mmc_data sh7724_sdhi_data = {
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX,
.tmio_caps = MMC_CAP_SDIO_IRQ, .capabilities = MMC_CAP_SDIO_IRQ,
}; };
static struct platform_device sdhi_cn9_device = { static struct platform_device sdhi_cn9_device = {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/sh_mobile_sdhi.h> #include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mfd/tmio.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
...@@ -468,10 +469,10 @@ static struct resource sdhi0_cn7_resources[] = { ...@@ -468,10 +469,10 @@ static struct resource sdhi0_cn7_resources[] = {
}, },
}; };
static struct sh_mobile_sdhi_info sh7724_sdhi0_data = { static struct tmio_mmc_data sh7724_sdhi0_data = {
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX,
.tmio_caps = MMC_CAP_SDIO_IRQ, .capabilities = MMC_CAP_SDIO_IRQ,
}; };
static struct platform_device sdhi0_cn7_device = { static struct platform_device sdhi0_cn7_device = {
...@@ -497,10 +498,10 @@ static struct resource sdhi1_cn8_resources[] = { ...@@ -497,10 +498,10 @@ static struct resource sdhi1_cn8_resources[] = {
}, },
}; };
static struct sh_mobile_sdhi_info sh7724_sdhi1_data = { static struct tmio_mmc_data sh7724_sdhi1_data = {
.dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI1_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI1_RX,
.tmio_caps = MMC_CAP_SDIO_IRQ, .capabilities = MMC_CAP_SDIO_IRQ,
}; };
static struct platform_device sdhi1_cn8_device = { static struct platform_device sdhi1_cn8_device = {
......
...@@ -112,6 +112,17 @@ config FSL_DMA ...@@ -112,6 +112,17 @@ config FSL_DMA
EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
some Txxx and Bxxx parts. some Txxx and Bxxx parts.
config FSL_RAID
tristate "Freescale RAID engine Support"
depends on FSL_SOC && !ASYNC_TX_ENABLE_CHANNEL_SWITCH
select DMA_ENGINE
select DMA_ENGINE_RAID
---help---
Enable support for Freescale RAID Engine. RAID Engine is
available on some QorIQ SoCs (like P5020/P5040). It has
the capability to offload memcpy, xor and pq computation
for raid5/6.
source "drivers/dma/hsu/Kconfig" source "drivers/dma/hsu/Kconfig"
config MPC512X_DMA config MPC512X_DMA
...@@ -347,6 +358,16 @@ config DMA_JZ4740 ...@@ -347,6 +358,16 @@ config DMA_JZ4740
select DMA_ENGINE select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS select DMA_VIRTUAL_CHANNELS
config DMA_JZ4780
tristate "JZ4780 DMA support"
depends on MACH_JZ4780
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
help
This selects support for the DMA controller in Ingenic JZ4780 SoCs.
If you have a board based on such a SoC and wish to use DMA for
devices which can use the DMA controller, say Y or M here.
config K3_DMA config K3_DMA
tristate "Hisilicon K3 DMA support" tristate "Hisilicon K3 DMA support"
depends on ARCH_HI3xxx depends on ARCH_HI3xxx
...@@ -414,6 +435,14 @@ config IMG_MDC_DMA ...@@ -414,6 +435,14 @@ config IMG_MDC_DMA
help help
Enable support for the IMG multi-threaded DMA controller (MDC). Enable support for the IMG multi-threaded DMA controller (MDC).
config XGENE_DMA
tristate "APM X-Gene DMA support"
select DMA_ENGINE
select DMA_ENGINE_RAID
select ASYNC_TX_ENABLE_CHANNEL_SWITCH
help
Enable support for the APM X-Gene SoC DMA engine.
config DMA_ENGINE config DMA_ENGINE
bool bool
......
...@@ -41,9 +41,11 @@ obj-$(CONFIG_DMA_OMAP) += omap-dma.o ...@@ -41,9 +41,11 @@ obj-$(CONFIG_DMA_OMAP) += omap-dma.o
obj-$(CONFIG_DMA_BCM2835) += bcm2835-dma.o obj-$(CONFIG_DMA_BCM2835) += bcm2835-dma.o
obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
obj-$(CONFIG_DMA_JZ4780) += dma-jz4780.o
obj-$(CONFIG_TI_CPPI41) += cppi41.o obj-$(CONFIG_TI_CPPI41) += cppi41.o
obj-$(CONFIG_K3_DMA) += k3dma.o obj-$(CONFIG_K3_DMA) += k3dma.o
obj-$(CONFIG_MOXART_DMA) += moxart-dma.o obj-$(CONFIG_MOXART_DMA) += moxart-dma.o
obj-$(CONFIG_FSL_RAID) += fsl_raid.o
obj-$(CONFIG_FSL_EDMA) += fsl-edma.o obj-$(CONFIG_FSL_EDMA) += fsl-edma.o
obj-$(CONFIG_QCOM_BAM_DMA) += qcom_bam_dma.o obj-$(CONFIG_QCOM_BAM_DMA) += qcom_bam_dma.o
obj-y += xilinx/ obj-y += xilinx/
...@@ -51,3 +53,4 @@ obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o ...@@ -51,3 +53,4 @@ obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o
obj-$(CONFIG_NBPFAXI_DMA) += nbpfaxi.o obj-$(CONFIG_NBPFAXI_DMA) += nbpfaxi.o
obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o
obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o
obj-$(CONFIG_XGENE_DMA) += xgene-dma.o
...@@ -15,10 +15,6 @@ ...@@ -15,10 +15,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is in this distribution in the file * The full GNU General Public License is in this distribution in the file
* called COPYING. * called COPYING.
* *
...@@ -1195,11 +1191,6 @@ static void pl08x_free_txd_list(struct pl08x_driver_data *pl08x, ...@@ -1195,11 +1191,6 @@ static void pl08x_free_txd_list(struct pl08x_driver_data *pl08x,
/* /*
* The DMA ENGINE API * The DMA ENGINE API
*/ */
static int pl08x_alloc_chan_resources(struct dma_chan *chan)
{
return 0;
}
static void pl08x_free_chan_resources(struct dma_chan *chan) static void pl08x_free_chan_resources(struct dma_chan *chan)
{ {
/* Ensure all queued descriptors are freed */ /* Ensure all queued descriptors are freed */
...@@ -2066,7 +2057,6 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2066,7 +2057,6 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
/* Initialize memcpy engine */ /* Initialize memcpy engine */
dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask); dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
pl08x->memcpy.dev = &adev->dev; pl08x->memcpy.dev = &adev->dev;
pl08x->memcpy.device_alloc_chan_resources = pl08x_alloc_chan_resources;
pl08x->memcpy.device_free_chan_resources = pl08x_free_chan_resources; pl08x->memcpy.device_free_chan_resources = pl08x_free_chan_resources;
pl08x->memcpy.device_prep_dma_memcpy = pl08x_prep_dma_memcpy; pl08x->memcpy.device_prep_dma_memcpy = pl08x_prep_dma_memcpy;
pl08x->memcpy.device_prep_dma_interrupt = pl08x_prep_dma_interrupt; pl08x->memcpy.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
...@@ -2085,7 +2075,6 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2085,7 +2075,6 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask); dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
dma_cap_set(DMA_CYCLIC, pl08x->slave.cap_mask); dma_cap_set(DMA_CYCLIC, pl08x->slave.cap_mask);
pl08x->slave.dev = &adev->dev; pl08x->slave.dev = &adev->dev;
pl08x->slave.device_alloc_chan_resources = pl08x_alloc_chan_resources;
pl08x->slave.device_free_chan_resources = pl08x_free_chan_resources; pl08x->slave.device_free_chan_resources = pl08x_free_chan_resources;
pl08x->slave.device_prep_dma_interrupt = pl08x_prep_dma_interrupt; pl08x->slave.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
pl08x->slave.device_tx_status = pl08x_dma_tx_status; pl08x->slave.device_tx_status = pl08x_dma_tx_status;
......
...@@ -65,6 +65,21 @@ static void atc_issue_pending(struct dma_chan *chan); ...@@ -65,6 +65,21 @@ static void atc_issue_pending(struct dma_chan *chan);
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
static inline unsigned int atc_get_xfer_width(dma_addr_t src, dma_addr_t dst,
size_t len)
{
unsigned int width;
if (!((src | dst | len) & 3))
width = 2;
else if (!((src | dst | len) & 1))
width = 1;
else
width = 0;
return width;
}
static struct at_desc *atc_first_active(struct at_dma_chan *atchan) static struct at_desc *atc_first_active(struct at_dma_chan *atchan)
{ {
return list_first_entry(&atchan->active_list, return list_first_entry(&atchan->active_list,
...@@ -659,16 +674,10 @@ atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, ...@@ -659,16 +674,10 @@ atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
* We can be a lot more clever here, but this should take care * We can be a lot more clever here, but this should take care
* of the most common optimization. * of the most common optimization.
*/ */
if (!((src | dest | len) & 3)) { src_width = dst_width = atc_get_xfer_width(src, dest, len);
ctrla = ATC_SRC_WIDTH_WORD | ATC_DST_WIDTH_WORD;
src_width = dst_width = 2; ctrla = ATC_SRC_WIDTH(src_width) |
} else if (!((src | dest | len) & 1)) { ATC_DST_WIDTH(dst_width);
ctrla = ATC_SRC_WIDTH_HALFWORD | ATC_DST_WIDTH_HALFWORD;
src_width = dst_width = 1;
} else {
ctrla = ATC_SRC_WIDTH_BYTE | ATC_DST_WIDTH_BYTE;
src_width = dst_width = 0;
}
for (offset = 0; offset < len; offset += xfer_count << src_width) { for (offset = 0; offset < len; offset += xfer_count << src_width) {
xfer_count = min_t(size_t, (len - offset) >> src_width, xfer_count = min_t(size_t, (len - offset) >> src_width,
...@@ -861,6 +870,144 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ...@@ -861,6 +870,144 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
return NULL; return NULL;
} }
/**
* atc_prep_dma_sg - prepare memory to memory scather-gather operation
* @chan: the channel to prepare operation on
* @dst_sg: destination scatterlist
* @dst_nents: number of destination scatterlist entries
* @src_sg: source scatterlist
* @src_nents: number of source scatterlist entries
* @flags: tx descriptor status flags
*/
static struct dma_async_tx_descriptor *
atc_prep_dma_sg(struct dma_chan *chan,
struct scatterlist *dst_sg, unsigned int dst_nents,
struct scatterlist *src_sg, unsigned int src_nents,
unsigned long flags)
{
struct at_dma_chan *atchan = to_at_dma_chan(chan);
struct at_desc *desc = NULL;
struct at_desc *first = NULL;
struct at_desc *prev = NULL;
unsigned int src_width;
unsigned int dst_width;
size_t xfer_count;
u32 ctrla;
u32 ctrlb;
size_t dst_len = 0, src_len = 0;
dma_addr_t dst = 0, src = 0;
size_t len = 0, total_len = 0;
if (unlikely(dst_nents == 0 || src_nents == 0))
return NULL;
if (unlikely(dst_sg == NULL || src_sg == NULL))
return NULL;
ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN
| ATC_SRC_ADDR_MODE_INCR
| ATC_DST_ADDR_MODE_INCR
| ATC_FC_MEM2MEM;
/*
* loop until there is either no more source or no more destination
* scatterlist entry
*/
while (true) {
/* prepare the next transfer */
if (dst_len == 0) {
/* no more destination scatterlist entries */
if (!dst_sg || !dst_nents)
break;
dst = sg_dma_address(dst_sg);
dst_len = sg_dma_len(dst_sg);
dst_sg = sg_next(dst_sg);
dst_nents--;
}
if (src_len == 0) {
/* no more source scatterlist entries */
if (!src_sg || !src_nents)
break;
src = sg_dma_address(src_sg);
src_len = sg_dma_len(src_sg);
src_sg = sg_next(src_sg);
src_nents--;
}
len = min_t(size_t, src_len, dst_len);
if (len == 0)
continue;
/* take care for the alignment */
src_width = dst_width = atc_get_xfer_width(src, dst, len);
ctrla = ATC_SRC_WIDTH(src_width) |
ATC_DST_WIDTH(dst_width);
/*
* The number of transfers to set up refer to the source width
* that depends on the alignment.
*/
xfer_count = len >> src_width;
if (xfer_count > ATC_BTSIZE_MAX) {
xfer_count = ATC_BTSIZE_MAX;
len = ATC_BTSIZE_MAX << src_width;
}
/* create the transfer */
desc = atc_desc_get(atchan);
if (!desc)
goto err_desc_get;
desc->lli.saddr = src;
desc->lli.daddr = dst;
desc->lli.ctrla = ctrla | xfer_count;
desc->lli.ctrlb = ctrlb;
desc->txd.cookie = 0;
desc->len = len;
/*
* Although we only need the transfer width for the first and
* the last descriptor, its easier to set it to all descriptors.
*/
desc->tx_width = src_width;
atc_desc_chain(&first, &prev, desc);
/* update the lengths and addresses for the next loop cycle */
dst_len -= len;
src_len -= len;
dst += len;
src += len;
total_len += len;
}
/* First descriptor of the chain embedds additional information */
first->txd.cookie = -EBUSY;
first->total_len = total_len;
/* set end-of-link to the last link descriptor of list*/
set_desc_eol(desc);
first->txd.flags = flags; /* client is in control of this ack */
return &first->txd;
err_desc_get:
atc_desc_put(atchan, first);
return NULL;
}
/** /**
* atc_dma_cyclic_check_values * atc_dma_cyclic_check_values
* Check for too big/unaligned periods and unaligned DMA buffer * Check for too big/unaligned periods and unaligned DMA buffer
...@@ -1461,8 +1608,10 @@ static int __init at_dma_probe(struct platform_device *pdev) ...@@ -1461,8 +1608,10 @@ static int __init at_dma_probe(struct platform_device *pdev)
/* setup platform data for each SoC */ /* setup platform data for each SoC */
dma_cap_set(DMA_MEMCPY, at91sam9rl_config.cap_mask); dma_cap_set(DMA_MEMCPY, at91sam9rl_config.cap_mask);
dma_cap_set(DMA_SG, at91sam9rl_config.cap_mask);
dma_cap_set(DMA_MEMCPY, at91sam9g45_config.cap_mask); dma_cap_set(DMA_MEMCPY, at91sam9g45_config.cap_mask);
dma_cap_set(DMA_SLAVE, at91sam9g45_config.cap_mask); dma_cap_set(DMA_SLAVE, at91sam9g45_config.cap_mask);
dma_cap_set(DMA_SG, at91sam9g45_config.cap_mask);
/* get DMA parameters from controller type */ /* get DMA parameters from controller type */
plat_dat = at_dma_get_driver_data(pdev); plat_dat = at_dma_get_driver_data(pdev);
...@@ -1582,11 +1731,15 @@ static int __init at_dma_probe(struct platform_device *pdev) ...@@ -1582,11 +1731,15 @@ static int __init at_dma_probe(struct platform_device *pdev)
atdma->dma_common.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; atdma->dma_common.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
} }
if (dma_has_cap(DMA_SG, atdma->dma_common.cap_mask))
atdma->dma_common.device_prep_dma_sg = atc_prep_dma_sg;
dma_writel(atdma, EN, AT_DMA_ENABLE); dma_writel(atdma, EN, AT_DMA_ENABLE);
dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n", dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s%s), %d channels\n",
dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "", dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ? "slave " : "", dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ? "slave " : "",
dma_has_cap(DMA_SG, atdma->dma_common.cap_mask) ? "sg-cpy " : "",
plat_dat->nr_channels); plat_dat->nr_channels);
dma_async_device_register(&atdma->dma_common); dma_async_device_register(&atdma->dma_common);
......
...@@ -1154,8 +1154,10 @@ static int at_xdmac_device_resume(struct dma_chan *chan) ...@@ -1154,8 +1154,10 @@ static int at_xdmac_device_resume(struct dma_chan *chan)
dev_dbg(chan2dev(chan), "%s\n", __func__); dev_dbg(chan2dev(chan), "%s\n", __func__);
spin_lock_bh(&atchan->lock); spin_lock_bh(&atchan->lock);
if (!at_xdmac_chan_is_paused(atchan)) if (!at_xdmac_chan_is_paused(atchan)) {
spin_unlock_bh(&atchan->lock);
return 0; return 0;
}
at_xdmac_write(atxdmac, AT_XDMAC_GRWR, atchan->mask); at_xdmac_write(atxdmac, AT_XDMAC_GRWR, atchan->mask);
clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status); clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status);
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define DRIVER_NAME "bestcomm-core" #define DRIVER_NAME "bestcomm-core"
/* MPC5200 device tree match tables */ /* MPC5200 device tree match tables */
static struct of_device_id mpc52xx_sram_ids[] = { static const struct of_device_id mpc52xx_sram_ids[] = {
{ .compatible = "fsl,mpc5200-sram", }, { .compatible = "fsl,mpc5200-sram", },
{ .compatible = "mpc5200-sram", }, { .compatible = "mpc5200-sram", },
{} {}
...@@ -481,7 +481,7 @@ static int mpc52xx_bcom_remove(struct platform_device *op) ...@@ -481,7 +481,7 @@ static int mpc52xx_bcom_remove(struct platform_device *op)
return 0; return 0;
} }
static struct of_device_id mpc52xx_bcom_of_match[] = { static const struct of_device_id mpc52xx_bcom_of_match[] = {
{ .compatible = "fsl,mpc5200-bestcomm", }, { .compatible = "fsl,mpc5200-bestcomm", },
{ .compatible = "mpc5200-bestcomm", }, { .compatible = "mpc5200-bestcomm", },
{}, {},
......
...@@ -7,10 +7,6 @@ ...@@ -7,10 +7,6 @@
* Free Software Foundation; either version 2 of the License, or (at your * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. * option) any later version.
* *
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/ */
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
...@@ -343,7 +339,7 @@ static void jz4740_dma_chan_irq(struct jz4740_dmaengine_chan *chan) ...@@ -343,7 +339,7 @@ static void jz4740_dma_chan_irq(struct jz4740_dmaengine_chan *chan)
{ {
spin_lock(&chan->vchan.lock); spin_lock(&chan->vchan.lock);
if (chan->desc) { if (chan->desc) {
if (chan->desc && chan->desc->cyclic) { if (chan->desc->cyclic) {
vchan_cyclic_callback(&chan->desc->vdesc); vchan_cyclic_callback(&chan->desc->vdesc);
} else { } else {
if (chan->next_sg == chan->desc->num_sgs) { if (chan->next_sg == chan->desc->num_sgs) {
...@@ -496,11 +492,6 @@ static enum dma_status jz4740_dma_tx_status(struct dma_chan *c, ...@@ -496,11 +492,6 @@ static enum dma_status jz4740_dma_tx_status(struct dma_chan *c,
return status; return status;
} }
static int jz4740_dma_alloc_chan_resources(struct dma_chan *c)
{
return 0;
}
static void jz4740_dma_free_chan_resources(struct dma_chan *c) static void jz4740_dma_free_chan_resources(struct dma_chan *c)
{ {
vchan_free_chan_resources(to_virt_chan(c)); vchan_free_chan_resources(to_virt_chan(c));
...@@ -543,7 +534,6 @@ static int jz4740_dma_probe(struct platform_device *pdev) ...@@ -543,7 +534,6 @@ static int jz4740_dma_probe(struct platform_device *pdev)
dma_cap_set(DMA_SLAVE, dd->cap_mask); dma_cap_set(DMA_SLAVE, dd->cap_mask);
dma_cap_set(DMA_CYCLIC, dd->cap_mask); dma_cap_set(DMA_CYCLIC, dd->cap_mask);
dd->device_alloc_chan_resources = jz4740_dma_alloc_chan_resources;
dd->device_free_chan_resources = jz4740_dma_free_chan_resources; dd->device_free_chan_resources = jz4740_dma_free_chan_resources;
dd->device_tx_status = jz4740_dma_tx_status; dd->device_tx_status = jz4740_dma_tx_status;
dd->device_issue_pending = jz4740_dma_issue_pending; dd->device_issue_pending = jz4740_dma_issue_pending;
......
此差异已折叠。
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the * The full GNU General Public License is included in this distribution in the
* file called COPYING. * file called COPYING.
*/ */
...@@ -355,20 +351,6 @@ struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) ...@@ -355,20 +351,6 @@ struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type)
} }
EXPORT_SYMBOL(dma_find_channel); EXPORT_SYMBOL(dma_find_channel);
/*
* net_dma_find_channel - find a channel for net_dma
* net_dma has alignment requirements
*/
struct dma_chan *net_dma_find_channel(void)
{
struct dma_chan *chan = dma_find_channel(DMA_MEMCPY);
if (chan && !is_dma_copy_aligned(chan->device, 1, 1, 1))
return NULL;
return chan;
}
EXPORT_SYMBOL(net_dma_find_channel);
/** /**
* dma_issue_pending_all - flush all pending operations across all channels * dma_issue_pending_all - flush all pending operations across all channels
*/ */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
config DW_DMAC_CORE config DW_DMAC_CORE
tristate "Synopsys DesignWare AHB DMA support" tristate
select DMA_ENGINE select DMA_ENGINE
config DW_DMAC config DW_DMAC
......
...@@ -230,7 +230,8 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) ...@@ -230,7 +230,8 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
/* ASSERT: channel is idle */ /* ASSERT: channel is idle */
if (dma_readl(dw, CH_EN) & dwc->mask) { if (dma_readl(dw, CH_EN) & dwc->mask) {
dev_err(chan2dev(&dwc->chan), dev_err(chan2dev(&dwc->chan),
"BUG: Attempted to start non-idle channel\n"); "%s: BUG: Attempted to start non-idle channel\n",
__func__);
dwc_dump_chan_regs(dwc); dwc_dump_chan_regs(dwc);
/* The tasklet will hopefully advance the queue... */ /* The tasklet will hopefully advance the queue... */
...@@ -814,11 +815,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ...@@ -814,11 +815,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
slave_sg_todev_fill_desc: slave_sg_todev_fill_desc:
desc = dwc_desc_get(dwc); desc = dwc_desc_get(dwc);
if (!desc) { if (!desc)
dev_err(chan2dev(chan),
"not enough descriptors available\n");
goto err_desc_get; goto err_desc_get;
}
desc->lli.sar = mem; desc->lli.sar = mem;
desc->lli.dar = reg; desc->lli.dar = reg;
...@@ -874,11 +872,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ...@@ -874,11 +872,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
slave_sg_fromdev_fill_desc: slave_sg_fromdev_fill_desc:
desc = dwc_desc_get(dwc); desc = dwc_desc_get(dwc);
if (!desc) { if (!desc)
dev_err(chan2dev(chan),
"not enough descriptors available\n");
goto err_desc_get; goto err_desc_get;
}
desc->lli.sar = reg; desc->lli.sar = reg;
desc->lli.dar = mem; desc->lli.dar = mem;
...@@ -922,6 +917,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ...@@ -922,6 +917,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
return &first->txd; return &first->txd;
err_desc_get: err_desc_get:
dev_err(chan2dev(chan),
"not enough descriptors available. Direction %d\n", direction);
dwc_desc_put(dwc, first); dwc_desc_put(dwc, first);
return NULL; return NULL;
} }
...@@ -1261,7 +1258,8 @@ int dw_dma_cyclic_start(struct dma_chan *chan) ...@@ -1261,7 +1258,8 @@ int dw_dma_cyclic_start(struct dma_chan *chan)
/* Assert channel is idle */ /* Assert channel is idle */
if (dma_readl(dw, CH_EN) & dwc->mask) { if (dma_readl(dw, CH_EN) & dwc->mask) {
dev_err(chan2dev(&dwc->chan), dev_err(chan2dev(&dwc->chan),
"BUG: Attempted to start non-idle channel\n"); "%s: BUG: Attempted to start non-idle channel\n",
__func__);
dwc_dump_chan_regs(dwc); dwc_dump_chan_regs(dwc);
spin_unlock_irqrestore(&dwc->lock, flags); spin_unlock_irqrestore(&dwc->lock, flags);
return -EBUSY; return -EBUSY;
......
...@@ -812,7 +812,7 @@ static int edma_alloc_chan_resources(struct dma_chan *chan) ...@@ -812,7 +812,7 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
LIST_HEAD(descs); LIST_HEAD(descs);
a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback, a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback,
chan, EVENTQ_DEFAULT); echan, EVENTQ_DEFAULT);
if (a_ch_num < 0) { if (a_ch_num < 0) {
ret = -ENODEV; ret = -ENODEV;
......
此差异已折叠。
/*
* drivers/dma/fsl_raid.h
*
* Freescale RAID Engine device driver
*
* Author:
* Harninder Rai <harninder.rai@freescale.com>
* Naveen Burmi <naveenburmi@freescale.com>
*
* Rewrite:
* Xuelin Shi <xuelin.shi@freescale.com>
* Copyright (c) 2010-2012 Freescale Semiconductor, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Freescale Semiconductor nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation, either version 2 of that License or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define FSL_RE_MAX_CHANS 4
#define FSL_RE_DPAA_MODE BIT(30)
#define FSL_RE_NON_DPAA_MODE BIT(31)
#define FSL_RE_GFM_POLY 0x1d000000
#define FSL_RE_ADD_JOB(x) ((x) << 16)
#define FSL_RE_RMVD_JOB(x) ((x) << 16)
#define FSL_RE_CFG1_CBSI 0x08000000
#define FSL_RE_CFG1_CBS0 0x00080000
#define FSL_RE_SLOT_FULL_SHIFT 8
#define FSL_RE_SLOT_FULL(x) ((x) >> FSL_RE_SLOT_FULL_SHIFT)
#define FSL_RE_SLOT_AVAIL_SHIFT 8
#define FSL_RE_SLOT_AVAIL(x) ((x) >> FSL_RE_SLOT_AVAIL_SHIFT)
#define FSL_RE_PQ_OPCODE 0x1B
#define FSL_RE_XOR_OPCODE 0x1A
#define FSL_RE_MOVE_OPCODE 0x8
#define FSL_RE_FRAME_ALIGN 16
#define FSL_RE_BLOCK_SIZE 0x3 /* 4096 bytes */
#define FSL_RE_CACHEABLE_IO 0x0
#define FSL_RE_BUFFER_OUTPUT 0x0
#define FSL_RE_INTR_ON_ERROR 0x1
#define FSL_RE_DATA_DEP 0x1
#define FSL_RE_ENABLE_DPI 0x0
#define FSL_RE_RING_SIZE 0x400
#define FSL_RE_RING_SIZE_MASK (FSL_RE_RING_SIZE - 1)
#define FSL_RE_RING_SIZE_SHIFT 8
#define FSL_RE_ADDR_BIT_SHIFT 4
#define FSL_RE_ADDR_BIT_MASK (BIT(FSL_RE_ADDR_BIT_SHIFT) - 1)
#define FSL_RE_ERROR 0x40000000
#define FSL_RE_INTR 0x80000000
#define FSL_RE_CLR_INTR 0x80000000
#define FSL_RE_PAUSE 0x80000000
#define FSL_RE_ENABLE 0x80000000
#define FSL_RE_REG_LIODN_MASK 0x00000FFF
#define FSL_RE_CDB_OPCODE_MASK 0xF8000000
#define FSL_RE_CDB_OPCODE_SHIFT 27
#define FSL_RE_CDB_EXCLEN_MASK 0x03000000
#define FSL_RE_CDB_EXCLEN_SHIFT 24
#define FSL_RE_CDB_EXCLQ1_MASK 0x00F00000
#define FSL_RE_CDB_EXCLQ1_SHIFT 20
#define FSL_RE_CDB_EXCLQ2_MASK 0x000F0000
#define FSL_RE_CDB_EXCLQ2_SHIFT 16
#define FSL_RE_CDB_BLKSIZE_MASK 0x0000C000
#define FSL_RE_CDB_BLKSIZE_SHIFT 14
#define FSL_RE_CDB_CACHE_MASK 0x00003000
#define FSL_RE_CDB_CACHE_SHIFT 12
#define FSL_RE_CDB_BUFFER_MASK 0x00000800
#define FSL_RE_CDB_BUFFER_SHIFT 11
#define FSL_RE_CDB_ERROR_MASK 0x00000400
#define FSL_RE_CDB_ERROR_SHIFT 10
#define FSL_RE_CDB_NRCS_MASK 0x0000003C
#define FSL_RE_CDB_NRCS_SHIFT 6
#define FSL_RE_CDB_DEPEND_MASK 0x00000008
#define FSL_RE_CDB_DEPEND_SHIFT 3
#define FSL_RE_CDB_DPI_MASK 0x00000004
#define FSL_RE_CDB_DPI_SHIFT 2
/*
* the largest cf block is 19*sizeof(struct cmpnd_frame), which is 304 bytes.
* here 19 = 1(cdb)+2(dest)+16(src), align to 64bytes, that is 320 bytes.
* the largest cdb block: struct pq_cdb which is 180 bytes, adding to cf block
* 320+180=500, align to 64bytes, that is 512 bytes.
*/
#define FSL_RE_CF_DESC_SIZE 320
#define FSL_RE_CF_CDB_SIZE 512
#define FSL_RE_CF_CDB_ALIGN 64
struct fsl_re_ctrl {
/* General Configuration Registers */
__be32 global_config; /* Global Configuration Register */
u8 rsvd1[4];
__be32 galois_field_config; /* Galois Field Configuration Register */
u8 rsvd2[4];
__be32 jq_wrr_config; /* WRR Configuration register */
u8 rsvd3[4];
__be32 crc_config; /* CRC Configuration register */
u8 rsvd4[228];
__be32 system_reset; /* System Reset Register */
u8 rsvd5[252];
__be32 global_status; /* Global Status Register */
u8 rsvd6[832];
__be32 re_liodn_base; /* LIODN Base Register */
u8 rsvd7[1712];
__be32 re_version_id; /* Version ID register of RE */
__be32 re_version_id_2; /* Version ID 2 register of RE */
u8 rsvd8[512];
__be32 host_config; /* Host I/F Configuration Register */
};
struct fsl_re_chan_cfg {
/* Registers for JR interface */
__be32 jr_config_0; /* Job Queue Configuration 0 Register */
__be32 jr_config_1; /* Job Queue Configuration 1 Register */
__be32 jr_interrupt_status; /* Job Queue Interrupt Status Register */
u8 rsvd1[4];
__be32 jr_command; /* Job Queue Command Register */
u8 rsvd2[4];
__be32 jr_status; /* Job Queue Status Register */
u8 rsvd3[228];
/* Input Ring */
__be32 inbring_base_h; /* Inbound Ring Base Address Register - High */
__be32 inbring_base_l; /* Inbound Ring Base Address Register - Low */
__be32 inbring_size; /* Inbound Ring Size Register */
u8 rsvd4[4];
__be32 inbring_slot_avail; /* Inbound Ring Slot Available Register */
u8 rsvd5[4];
__be32 inbring_add_job; /* Inbound Ring Add Job Register */
u8 rsvd6[4];
__be32 inbring_cnsmr_indx; /* Inbound Ring Consumer Index Register */
u8 rsvd7[220];
/* Output Ring */
__be32 oubring_base_h; /* Outbound Ring Base Address Register - High */
__be32 oubring_base_l; /* Outbound Ring Base Address Register - Low */
__be32 oubring_size; /* Outbound Ring Size Register */
u8 rsvd8[4];
__be32 oubring_job_rmvd; /* Outbound Ring Job Removed Register */
u8 rsvd9[4];
__be32 oubring_slot_full; /* Outbound Ring Slot Full Register */
u8 rsvd10[4];
__be32 oubring_prdcr_indx; /* Outbound Ring Producer Index */
};
/*
* Command Descriptor Block (CDB) for unicast move command.
* In RAID Engine terms, memcpy is done through move command
*/
struct fsl_re_move_cdb {
__be32 cdb32;
};
/* Data protection/integrity related fields */
#define FSL_RE_DPI_APPS_MASK 0xC0000000
#define FSL_RE_DPI_APPS_SHIFT 30
#define FSL_RE_DPI_REF_MASK 0x30000000
#define FSL_RE_DPI_REF_SHIFT 28
#define FSL_RE_DPI_GUARD_MASK 0x0C000000
#define FSL_RE_DPI_GUARD_SHIFT 26
#define FSL_RE_DPI_ATTR_MASK 0x03000000
#define FSL_RE_DPI_ATTR_SHIFT 24
#define FSL_RE_DPI_META_MASK 0x0000FFFF
struct fsl_re_dpi {
__be32 dpi32;
__be32 ref;
};
/*
* CDB for GenQ command. In RAID Engine terminology, XOR is
* done through this command
*/
struct fsl_re_xor_cdb {
__be32 cdb32;
u8 gfm[16];
struct fsl_re_dpi dpi_dest_spec;
struct fsl_re_dpi dpi_src_spec[16];
};
/* CDB for no-op command */
struct fsl_re_noop_cdb {
__be32 cdb32;
};
/*
* CDB for GenQQ command. In RAID Engine terminology, P/Q is
* done through this command
*/
struct fsl_re_pq_cdb {
__be32 cdb32;
u8 gfm_q1[16];
u8 gfm_q2[16];
struct fsl_re_dpi dpi_dest_spec[2];
struct fsl_re_dpi dpi_src_spec[16];
};
/* Compound frame */
#define FSL_RE_CF_ADDR_HIGH_MASK 0x000000FF
#define FSL_RE_CF_EXT_MASK 0x80000000
#define FSL_RE_CF_EXT_SHIFT 31
#define FSL_RE_CF_FINAL_MASK 0x40000000
#define FSL_RE_CF_FINAL_SHIFT 30
#define FSL_RE_CF_LENGTH_MASK 0x000FFFFF
#define FSL_RE_CF_BPID_MASK 0x00FF0000
#define FSL_RE_CF_BPID_SHIFT 16
#define FSL_RE_CF_OFFSET_MASK 0x00001FFF
struct fsl_re_cmpnd_frame {
__be32 addr_high;
__be32 addr_low;
__be32 efrl32;
__be32 rbro32;
};
/* Frame descriptor */
#define FSL_RE_HWDESC_LIODN_MASK 0x3F000000
#define FSL_RE_HWDESC_LIODN_SHIFT 24
#define FSL_RE_HWDESC_BPID_MASK 0x00FF0000
#define FSL_RE_HWDESC_BPID_SHIFT 16
#define FSL_RE_HWDESC_ELIODN_MASK 0x0000F000
#define FSL_RE_HWDESC_ELIODN_SHIFT 12
#define FSL_RE_HWDESC_FMT_SHIFT 29
#define FSL_RE_HWDESC_FMT_MASK (0x3 << FSL_RE_HWDESC_FMT_SHIFT)
struct fsl_re_hw_desc {
__be32 lbea32;
__be32 addr_low;
__be32 fmt32;
__be32 status;
};
/* Raid Engine device private data */
struct fsl_re_drv_private {
u8 total_chans;
struct dma_device dma_dev;
struct fsl_re_ctrl *re_regs;
struct fsl_re_chan *re_jrs[FSL_RE_MAX_CHANS];
struct dma_pool *cf_desc_pool;
struct dma_pool *hw_desc_pool;
};
/* Per job ring data structure */
struct fsl_re_chan {
char name[16];
spinlock_t desc_lock; /* queue lock */
struct list_head ack_q; /* wait to acked queue */
struct list_head active_q; /* already issued on hw, not completed */
struct list_head submit_q;
struct list_head free_q; /* alloc available queue */
struct device *dev;
struct fsl_re_drv_private *re_dev;
struct dma_chan chan;
struct fsl_re_chan_cfg *jrregs;
int irq;
struct tasklet_struct irqtask;
u32 alloc_count;
/* hw descriptor ring for inbound queue*/
dma_addr_t inb_phys_addr;
struct fsl_re_hw_desc *inb_ring_virt_addr;
u32 inb_count;
/* hw descriptor ring for outbound queue */
dma_addr_t oub_phys_addr;
struct fsl_re_hw_desc *oub_ring_virt_addr;
u32 oub_count;
};
/* Async transaction descriptor */
struct fsl_re_desc {
struct dma_async_tx_descriptor async_tx;
struct list_head node;
struct fsl_re_hw_desc hwdesc;
struct fsl_re_chan *re_chan;
/* hwdesc will point to cf_addr */
void *cf_addr;
dma_addr_t cf_paddr;
void *cdb_addr;
dma_addr_t cdb_paddr;
int status;
};
...@@ -689,11 +689,6 @@ static int mdc_slave_config(struct dma_chan *chan, ...@@ -689,11 +689,6 @@ static int mdc_slave_config(struct dma_chan *chan,
return 0; return 0;
} }
static int mdc_alloc_chan_resources(struct dma_chan *chan)
{
return 0;
}
static void mdc_free_chan_resources(struct dma_chan *chan) static void mdc_free_chan_resources(struct dma_chan *chan)
{ {
struct mdc_chan *mchan = to_mdc_chan(chan); struct mdc_chan *mchan = to_mdc_chan(chan);
...@@ -910,7 +905,6 @@ static int mdc_dma_probe(struct platform_device *pdev) ...@@ -910,7 +905,6 @@ static int mdc_dma_probe(struct platform_device *pdev)
mdma->dma_dev.device_prep_slave_sg = mdc_prep_slave_sg; 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_cyclic = mdc_prep_dma_cyclic;
mdma->dma_dev.device_prep_dma_memcpy = mdc_prep_dma_memcpy; 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_free_chan_resources = mdc_free_chan_resources;
mdma->dma_dev.device_tx_status = mdc_tx_status; mdma->dma_dev.device_tx_status = mdc_tx_status;
mdma->dma_dev.device_issue_pending = mdc_issue_pending; mdma->dma_dev.device_issue_pending = mdc_issue_pending;
......
...@@ -1260,6 +1260,7 @@ static void sdma_issue_pending(struct dma_chan *chan) ...@@ -1260,6 +1260,7 @@ static void sdma_issue_pending(struct dma_chan *chan)
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 34 #define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 34
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2 38 #define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2 38
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V3 41
static void sdma_add_scripts(struct sdma_engine *sdma, static void sdma_add_scripts(struct sdma_engine *sdma,
const struct sdma_script_start_addrs *addr) const struct sdma_script_start_addrs *addr)
...@@ -1306,6 +1307,9 @@ static void sdma_load_firmware(const struct firmware *fw, void *context) ...@@ -1306,6 +1307,9 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
case 2: case 2:
sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2; sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2;
break; break;
case 3:
sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V3;
break;
default: default:
dev_err(sdma->dev, "unknown firmware version\n"); dev_err(sdma->dev, "unknown firmware version\n");
goto err_firmware; goto err_firmware;
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* The full GNU General Public License is included in this distribution in * The full GNU General Public License is included in this distribution in
* the file called "COPYING". * the file called "COPYING".
* *
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* The full GNU General Public License is included in this distribution in * The full GNU General Public License is included in this distribution in
* the file called "COPYING". * the file called "COPYING".
* *
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the * The full GNU General Public License is included in this distribution in the
* file called COPYING. * file called COPYING.
*/ */
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* The full GNU General Public License is included in this distribution in * The full GNU General Public License is included in this distribution in
* the file called "COPYING". * the file called "COPYING".
* *
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the * The full GNU General Public License is included in this distribution in the
* file called COPYING. * file called COPYING.
*/ */
......
...@@ -15,10 +15,6 @@ ...@@ -15,10 +15,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* The full GNU General Public License is included in this distribution in * The full GNU General Public License is included in this distribution in
* the file called "COPYING". * the file called "COPYING".
* *
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the * The full GNU General Public License is included in this distribution in the
* file called COPYING. * file called COPYING.
*/ */
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* The full GNU General Public License is included in this distribution in * The full GNU General Public License is included in this distribution in
* the file called "COPYING". * the file called "COPYING".
* *
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the * The full GNU General Public License is included in this distribution in the
* file called COPYING. * file called COPYING.
*/ */
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
*/ */
/* /*
......
...@@ -313,11 +313,6 @@ static void k3_dma_tasklet(unsigned long arg) ...@@ -313,11 +313,6 @@ static void k3_dma_tasklet(unsigned long arg)
} }
} }
static int k3_dma_alloc_chan_resources(struct dma_chan *chan)
{
return 0;
}
static void k3_dma_free_chan_resources(struct dma_chan *chan) static void k3_dma_free_chan_resources(struct dma_chan *chan)
{ {
struct k3_dma_chan *c = to_k3_chan(chan); struct k3_dma_chan *c = to_k3_chan(chan);
...@@ -654,7 +649,7 @@ static void k3_dma_free_desc(struct virt_dma_desc *vd) ...@@ -654,7 +649,7 @@ static void k3_dma_free_desc(struct virt_dma_desc *vd)
kfree(ds); kfree(ds);
} }
static struct of_device_id k3_pdma_dt_ids[] = { static const struct of_device_id k3_pdma_dt_ids[] = {
{ .compatible = "hisilicon,k3-dma-1.0", }, { .compatible = "hisilicon,k3-dma-1.0", },
{} {}
}; };
...@@ -728,7 +723,6 @@ static int k3_dma_probe(struct platform_device *op) ...@@ -728,7 +723,6 @@ static int k3_dma_probe(struct platform_device *op)
dma_cap_set(DMA_SLAVE, d->slave.cap_mask); dma_cap_set(DMA_SLAVE, d->slave.cap_mask);
dma_cap_set(DMA_MEMCPY, d->slave.cap_mask); dma_cap_set(DMA_MEMCPY, d->slave.cap_mask);
d->slave.dev = &op->dev; d->slave.dev = &op->dev;
d->slave.device_alloc_chan_resources = k3_dma_alloc_chan_resources;
d->slave.device_free_chan_resources = k3_dma_free_chan_resources; d->slave.device_free_chan_resources = k3_dma_free_chan_resources;
d->slave.device_tx_status = k3_dma_tx_status; d->slave.device_tx_status = k3_dma_tx_status;
d->slave.device_prep_dma_memcpy = k3_dma_prep_memcpy; d->slave.device_prep_dma_memcpy = k3_dma_prep_memcpy;
......
...@@ -973,7 +973,7 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, int idx, int irq) ...@@ -973,7 +973,7 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, int idx, int irq)
return 0; return 0;
} }
static struct of_device_id mmp_pdma_dt_ids[] = { static const struct of_device_id mmp_pdma_dt_ids[] = {
{ .compatible = "marvell,pdma-1.0", }, { .compatible = "marvell,pdma-1.0", },
{} {}
}; };
......
...@@ -613,7 +613,7 @@ struct dma_chan *mmp_tdma_xlate(struct of_phandle_args *dma_spec, ...@@ -613,7 +613,7 @@ struct dma_chan *mmp_tdma_xlate(struct of_phandle_args *dma_spec,
return dma_request_channel(mask, mmp_tdma_filter_fn, &param); return dma_request_channel(mask, mmp_tdma_filter_fn, &param);
} }
static struct of_device_id mmp_tdma_dt_ids[] = { static const struct of_device_id mmp_tdma_dt_ids[] = {
{ .compatible = "marvell,adma-1.0", .data = (void *)MMP_AUD_TDMA}, { .compatible = "marvell,adma-1.0", .data = (void *)MMP_AUD_TDMA},
{ .compatible = "marvell,pxa910-squ", .data = (void *)PXA910_SQU}, { .compatible = "marvell,pxa910-squ", .data = (void *)PXA910_SQU},
{} {}
......
...@@ -21,10 +21,6 @@ ...@@ -21,10 +21,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the * The full GNU General Public License is included in this distribution in the
* file called COPYING. * file called COPYING.
*/ */
...@@ -1072,7 +1068,7 @@ static int mpc_dma_remove(struct platform_device *op) ...@@ -1072,7 +1068,7 @@ static int mpc_dma_remove(struct platform_device *op)
return 0; return 0;
} }
static struct of_device_id mpc_dma_match[] = { static const struct of_device_id mpc_dma_match[] = {
{ .compatible = "fsl,mpc5121-dma", }, { .compatible = "fsl,mpc5121-dma", },
{ .compatible = "fsl,mpc8308-dma", }, { .compatible = "fsl,mpc8308-dma", },
{}, {},
......
...@@ -10,10 +10,6 @@ ...@@ -10,10 +10,6 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <linux/init.h> #include <linux/init.h>
...@@ -1249,7 +1245,7 @@ static int mv_xor_remove(struct platform_device *pdev) ...@@ -1249,7 +1245,7 @@ static int mv_xor_remove(struct platform_device *pdev)
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id mv_xor_dt_ids[] = { static const struct of_device_id mv_xor_dt_ids[] = {
{ .compatible = "marvell,orion-xor", }, { .compatible = "marvell,orion-xor", },
{}, {},
}; };
......
...@@ -9,10 +9,6 @@ ...@@ -9,10 +9,6 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details. * for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifndef MV_XOR_H #ifndef MV_XOR_H
......
...@@ -949,6 +949,7 @@ static int pch_dma_probe(struct pci_dev *pdev, ...@@ -949,6 +949,7 @@ static int pch_dma_probe(struct pci_dev *pdev,
err_disable_pdev: err_disable_pdev:
pci_disable_device(pdev); pci_disable_device(pdev);
err_free_mem: err_free_mem:
kfree(pd);
return err; return err;
} }
......
...@@ -556,7 +556,7 @@ static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[], ...@@ -556,7 +556,7 @@ static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
buf[0] = CMD_DMAADDH; buf[0] = CMD_DMAADDH;
buf[0] |= (da << 1); buf[0] |= (da << 1);
*((u16 *)&buf[1]) = val; *((__le16 *)&buf[1]) = cpu_to_le16(val);
PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n", PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
da == 1 ? "DA" : "SA", val); da == 1 ? "DA" : "SA", val);
...@@ -710,7 +710,7 @@ static inline u32 _emit_MOV(unsigned dry_run, u8 buf[], ...@@ -710,7 +710,7 @@ static inline u32 _emit_MOV(unsigned dry_run, u8 buf[],
buf[0] = CMD_DMAMOV; buf[0] = CMD_DMAMOV;
buf[1] = dst; buf[1] = dst;
*((u32 *)&buf[2]) = val; *((__le32 *)&buf[2]) = cpu_to_le32(val);
PL330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n", PL330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n",
dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val); dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val);
...@@ -888,7 +888,7 @@ static inline u32 _emit_GO(unsigned dry_run, u8 buf[], ...@@ -888,7 +888,7 @@ static inline u32 _emit_GO(unsigned dry_run, u8 buf[],
buf[1] = chan & 0x7; buf[1] = chan & 0x7;
*((u32 *)&buf[2]) = addr; *((__le32 *)&buf[2]) = cpu_to_le32(addr);
return SZ_DMAGO; return SZ_DMAGO;
} }
...@@ -928,7 +928,7 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd, ...@@ -928,7 +928,7 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd,
} }
writel(val, regs + DBGINST0); writel(val, regs + DBGINST0);
val = *((u32 *)&insn[2]); val = le32_to_cpu(*((__le32 *)&insn[2]));
writel(val, regs + DBGINST1); writel(val, regs + DBGINST1);
/* If timed out due to halted state-machine */ /* If timed out due to halted state-machine */
...@@ -2162,7 +2162,7 @@ static int pl330_terminate_all(struct dma_chan *chan) ...@@ -2162,7 +2162,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
* DMA transfer again. This pause feature was implemented to * DMA transfer again. This pause feature was implemented to
* allow safely read residue before channel termination. * allow safely read residue before channel termination.
*/ */
int pl330_pause(struct dma_chan *chan) static int pl330_pause(struct dma_chan *chan)
{ {
struct dma_pl330_chan *pch = to_pchan(chan); struct dma_pl330_chan *pch = to_pchan(chan);
struct pl330_dmac *pl330 = pch->dmac; struct pl330_dmac *pl330 = pch->dmac;
...@@ -2203,8 +2203,8 @@ static void pl330_free_chan_resources(struct dma_chan *chan) ...@@ -2203,8 +2203,8 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
pm_runtime_put_autosuspend(pch->dmac->ddma.dev); pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
} }
int pl330_get_current_xferred_count(struct dma_pl330_chan *pch, static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch,
struct dma_pl330_desc *desc) struct dma_pl330_desc *desc)
{ {
struct pl330_thread *thrd = pch->thread; struct pl330_thread *thrd = pch->thread;
struct pl330_dmac *pl330 = pch->dmac; struct pl330_dmac *pl330 = pch->dmac;
...@@ -2259,7 +2259,17 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, ...@@ -2259,7 +2259,17 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
transferred = 0; transferred = 0;
residual += desc->bytes_requested - transferred; residual += desc->bytes_requested - transferred;
if (desc->txd.cookie == cookie) { if (desc->txd.cookie == cookie) {
ret = desc->status; switch (desc->status) {
case DONE:
ret = DMA_COMPLETE;
break;
case PREP:
case BUSY:
ret = DMA_IN_PROGRESS;
break;
default:
WARN_ON(1);
}
break; break;
} }
if (desc->last) if (desc->last)
......
...@@ -16,10 +16,6 @@ ...@@ -16,10 +16,6 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the * The full GNU General Public License is included in this distribution in the
* file called COPYING. * file called COPYING.
*/ */
......
...@@ -171,6 +171,35 @@ static const struct reg_offset_data bam_v1_4_reg_info[] = { ...@@ -171,6 +171,35 @@ static const struct reg_offset_data bam_v1_4_reg_info[] = {
[BAM_P_FIFO_SIZES] = { 0x1820, 0x00, 0x1000, 0x00 }, [BAM_P_FIFO_SIZES] = { 0x1820, 0x00, 0x1000, 0x00 },
}; };
static const struct reg_offset_data bam_v1_7_reg_info[] = {
[BAM_CTRL] = { 0x00000, 0x00, 0x00, 0x00 },
[BAM_REVISION] = { 0x01000, 0x00, 0x00, 0x00 },
[BAM_NUM_PIPES] = { 0x01008, 0x00, 0x00, 0x00 },
[BAM_DESC_CNT_TRSHLD] = { 0x00008, 0x00, 0x00, 0x00 },
[BAM_IRQ_SRCS] = { 0x03010, 0x00, 0x00, 0x00 },
[BAM_IRQ_SRCS_MSK] = { 0x03014, 0x00, 0x00, 0x00 },
[BAM_IRQ_SRCS_UNMASKED] = { 0x03018, 0x00, 0x00, 0x00 },
[BAM_IRQ_STTS] = { 0x00014, 0x00, 0x00, 0x00 },
[BAM_IRQ_CLR] = { 0x00018, 0x00, 0x00, 0x00 },
[BAM_IRQ_EN] = { 0x0001C, 0x00, 0x00, 0x00 },
[BAM_CNFG_BITS] = { 0x0007C, 0x00, 0x00, 0x00 },
[BAM_IRQ_SRCS_EE] = { 0x03000, 0x00, 0x00, 0x1000 },
[BAM_IRQ_SRCS_MSK_EE] = { 0x03004, 0x00, 0x00, 0x1000 },
[BAM_P_CTRL] = { 0x13000, 0x1000, 0x00, 0x00 },
[BAM_P_RST] = { 0x13004, 0x1000, 0x00, 0x00 },
[BAM_P_HALT] = { 0x13008, 0x1000, 0x00, 0x00 },
[BAM_P_IRQ_STTS] = { 0x13010, 0x1000, 0x00, 0x00 },
[BAM_P_IRQ_CLR] = { 0x13014, 0x1000, 0x00, 0x00 },
[BAM_P_IRQ_EN] = { 0x13018, 0x1000, 0x00, 0x00 },
[BAM_P_EVNT_DEST_ADDR] = { 0x1382C, 0x00, 0x1000, 0x00 },
[BAM_P_EVNT_REG] = { 0x13818, 0x00, 0x1000, 0x00 },
[BAM_P_SW_OFSTS] = { 0x13800, 0x00, 0x1000, 0x00 },
[BAM_P_DATA_FIFO_ADDR] = { 0x13824, 0x00, 0x1000, 0x00 },
[BAM_P_DESC_FIFO_ADDR] = { 0x1381C, 0x00, 0x1000, 0x00 },
[BAM_P_EVNT_GEN_TRSHLD] = { 0x13828, 0x00, 0x1000, 0x00 },
[BAM_P_FIFO_SIZES] = { 0x13820, 0x00, 0x1000, 0x00 },
};
/* BAM CTRL */ /* BAM CTRL */
#define BAM_SW_RST BIT(0) #define BAM_SW_RST BIT(0)
#define BAM_EN BIT(1) #define BAM_EN BIT(1)
...@@ -1051,6 +1080,7 @@ static void bam_channel_init(struct bam_device *bdev, struct bam_chan *bchan, ...@@ -1051,6 +1080,7 @@ static void bam_channel_init(struct bam_device *bdev, struct bam_chan *bchan,
static const struct of_device_id bam_of_match[] = { static const struct of_device_id bam_of_match[] = {
{ .compatible = "qcom,bam-v1.3.0", .data = &bam_v1_3_reg_info }, { .compatible = "qcom,bam-v1.3.0", .data = &bam_v1_3_reg_info },
{ .compatible = "qcom,bam-v1.4.0", .data = &bam_v1_4_reg_info }, { .compatible = "qcom,bam-v1.4.0", .data = &bam_v1_4_reg_info },
{ .compatible = "qcom,bam-v1.7.0", .data = &bam_v1_7_reg_info },
{} {}
}; };
...@@ -1113,7 +1143,7 @@ static int bam_dma_probe(struct platform_device *pdev) ...@@ -1113,7 +1143,7 @@ static int bam_dma_probe(struct platform_device *pdev)
if (!bdev->channels) { if (!bdev->channels) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_disable_clk; goto err_tasklet_kill;
} }
/* allocate and initialize channels */ /* allocate and initialize channels */
...@@ -1125,7 +1155,7 @@ static int bam_dma_probe(struct platform_device *pdev) ...@@ -1125,7 +1155,7 @@ static int bam_dma_probe(struct platform_device *pdev)
ret = devm_request_irq(bdev->dev, bdev->irq, bam_dma_irq, ret = devm_request_irq(bdev->dev, bdev->irq, bam_dma_irq,
IRQF_TRIGGER_HIGH, "bam_dma", bdev); IRQF_TRIGGER_HIGH, "bam_dma", bdev);
if (ret) if (ret)
goto err_disable_clk; goto err_bam_channel_exit;
/* set max dma segment size */ /* set max dma segment size */
bdev->common.dev = bdev->dev; bdev->common.dev = bdev->dev;
...@@ -1133,7 +1163,7 @@ static int bam_dma_probe(struct platform_device *pdev) ...@@ -1133,7 +1163,7 @@ static int bam_dma_probe(struct platform_device *pdev)
ret = dma_set_max_seg_size(bdev->common.dev, BAM_MAX_DATA_SIZE); ret = dma_set_max_seg_size(bdev->common.dev, BAM_MAX_DATA_SIZE);
if (ret) { if (ret) {
dev_err(bdev->dev, "cannot set maximum segment size\n"); dev_err(bdev->dev, "cannot set maximum segment size\n");
goto err_disable_clk; goto err_bam_channel_exit;
} }
platform_set_drvdata(pdev, bdev); platform_set_drvdata(pdev, bdev);
...@@ -1161,7 +1191,7 @@ static int bam_dma_probe(struct platform_device *pdev) ...@@ -1161,7 +1191,7 @@ static int bam_dma_probe(struct platform_device *pdev)
ret = dma_async_device_register(&bdev->common); ret = dma_async_device_register(&bdev->common);
if (ret) { if (ret) {
dev_err(bdev->dev, "failed to register dma async device\n"); dev_err(bdev->dev, "failed to register dma async device\n");
goto err_disable_clk; goto err_bam_channel_exit;
} }
ret = of_dma_controller_register(pdev->dev.of_node, bam_dma_xlate, ret = of_dma_controller_register(pdev->dev.of_node, bam_dma_xlate,
...@@ -1173,8 +1203,14 @@ static int bam_dma_probe(struct platform_device *pdev) ...@@ -1173,8 +1203,14 @@ static int bam_dma_probe(struct platform_device *pdev)
err_unregister_dma: err_unregister_dma:
dma_async_device_unregister(&bdev->common); dma_async_device_unregister(&bdev->common);
err_bam_channel_exit:
for (i = 0; i < bdev->num_channels; i++)
tasklet_kill(&bdev->channels[i].vc.task);
err_tasklet_kill:
tasklet_kill(&bdev->task);
err_disable_clk: err_disable_clk:
clk_disable_unprepare(bdev->bamclk); clk_disable_unprepare(bdev->bamclk);
return ret; return ret;
} }
......
...@@ -749,11 +749,6 @@ static int s3c24xx_dma_terminate_all(struct dma_chan *chan) ...@@ -749,11 +749,6 @@ static int s3c24xx_dma_terminate_all(struct dma_chan *chan)
return ret; return ret;
} }
static int s3c24xx_dma_alloc_chan_resources(struct dma_chan *chan)
{
return 0;
}
static void s3c24xx_dma_free_chan_resources(struct dma_chan *chan) static void s3c24xx_dma_free_chan_resources(struct dma_chan *chan)
{ {
/* Ensure all queued descriptors are freed */ /* Ensure all queued descriptors are freed */
...@@ -1238,7 +1233,7 @@ static int s3c24xx_dma_probe(struct platform_device *pdev) ...@@ -1238,7 +1233,7 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
if (!s3cdma->phy_chans) if (!s3cdma->phy_chans)
return -ENOMEM; return -ENOMEM;
/* aquire irqs and clocks for all physical channels */ /* acquire irqs and clocks for all physical channels */
for (i = 0; i < pdata->num_phy_channels; i++) { for (i = 0; i < pdata->num_phy_channels; i++) {
struct s3c24xx_dma_phy *phy = &s3cdma->phy_chans[i]; struct s3c24xx_dma_phy *phy = &s3cdma->phy_chans[i];
char clk_name[6]; char clk_name[6];
...@@ -1266,7 +1261,7 @@ static int s3c24xx_dma_probe(struct platform_device *pdev) ...@@ -1266,7 +1261,7 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
sprintf(clk_name, "dma.%d", i); sprintf(clk_name, "dma.%d", i);
phy->clk = devm_clk_get(&pdev->dev, clk_name); phy->clk = devm_clk_get(&pdev->dev, clk_name);
if (IS_ERR(phy->clk) && sdata->has_clocks) { if (IS_ERR(phy->clk) && sdata->has_clocks) {
dev_err(&pdev->dev, "unable to aquire clock for channel %d, error %lu", dev_err(&pdev->dev, "unable to acquire clock for channel %d, error %lu\n",
i, PTR_ERR(phy->clk)); i, PTR_ERR(phy->clk));
continue; continue;
} }
...@@ -1290,8 +1285,6 @@ static int s3c24xx_dma_probe(struct platform_device *pdev) ...@@ -1290,8 +1285,6 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
dma_cap_set(DMA_MEMCPY, s3cdma->memcpy.cap_mask); dma_cap_set(DMA_MEMCPY, s3cdma->memcpy.cap_mask);
dma_cap_set(DMA_PRIVATE, s3cdma->memcpy.cap_mask); dma_cap_set(DMA_PRIVATE, s3cdma->memcpy.cap_mask);
s3cdma->memcpy.dev = &pdev->dev; s3cdma->memcpy.dev = &pdev->dev;
s3cdma->memcpy.device_alloc_chan_resources =
s3c24xx_dma_alloc_chan_resources;
s3cdma->memcpy.device_free_chan_resources = s3cdma->memcpy.device_free_chan_resources =
s3c24xx_dma_free_chan_resources; s3c24xx_dma_free_chan_resources;
s3cdma->memcpy.device_prep_dma_memcpy = s3c24xx_dma_prep_memcpy; s3cdma->memcpy.device_prep_dma_memcpy = s3c24xx_dma_prep_memcpy;
...@@ -1305,8 +1298,6 @@ static int s3c24xx_dma_probe(struct platform_device *pdev) ...@@ -1305,8 +1298,6 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
dma_cap_set(DMA_CYCLIC, s3cdma->slave.cap_mask); dma_cap_set(DMA_CYCLIC, s3cdma->slave.cap_mask);
dma_cap_set(DMA_PRIVATE, s3cdma->slave.cap_mask); dma_cap_set(DMA_PRIVATE, s3cdma->slave.cap_mask);
s3cdma->slave.dev = &pdev->dev; s3cdma->slave.dev = &pdev->dev;
s3cdma->slave.device_alloc_chan_resources =
s3c24xx_dma_alloc_chan_resources;
s3cdma->slave.device_free_chan_resources = s3cdma->slave.device_free_chan_resources =
s3c24xx_dma_free_chan_resources; s3c24xx_dma_free_chan_resources;
s3cdma->slave.device_tx_status = s3c24xx_dma_tx_status; s3cdma->slave.device_tx_status = s3c24xx_dma_tx_status;
......
...@@ -389,11 +389,6 @@ static void sa11x0_dma_tasklet(unsigned long arg) ...@@ -389,11 +389,6 @@ static void sa11x0_dma_tasklet(unsigned long arg)
} }
static int sa11x0_dma_alloc_chan_resources(struct dma_chan *chan)
{
return 0;
}
static void sa11x0_dma_free_chan_resources(struct dma_chan *chan) static void sa11x0_dma_free_chan_resources(struct dma_chan *chan)
{ {
struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan); struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
...@@ -835,7 +830,6 @@ static int sa11x0_dma_init_dmadev(struct dma_device *dmadev, ...@@ -835,7 +830,6 @@ static int sa11x0_dma_init_dmadev(struct dma_device *dmadev,
INIT_LIST_HEAD(&dmadev->channels); INIT_LIST_HEAD(&dmadev->channels);
dmadev->dev = dev; dmadev->dev = dev;
dmadev->device_alloc_chan_resources = sa11x0_dma_alloc_chan_resources;
dmadev->device_free_chan_resources = sa11x0_dma_free_chan_resources; dmadev->device_free_chan_resources = sa11x0_dma_free_chan_resources;
dmadev->device_config = sa11x0_dma_device_config; dmadev->device_config = sa11x0_dma_device_config;
dmadev->device_pause = sa11x0_dma_device_pause; dmadev->device_pause = sa11x0_dma_device_pause;
...@@ -948,6 +942,12 @@ static int sa11x0_dma_probe(struct platform_device *pdev) ...@@ -948,6 +942,12 @@ static int sa11x0_dma_probe(struct platform_device *pdev)
dma_cap_set(DMA_CYCLIC, d->slave.cap_mask); dma_cap_set(DMA_CYCLIC, d->slave.cap_mask);
d->slave.device_prep_slave_sg = sa11x0_dma_prep_slave_sg; d->slave.device_prep_slave_sg = sa11x0_dma_prep_slave_sg;
d->slave.device_prep_dma_cyclic = sa11x0_dma_prep_dma_cyclic; d->slave.device_prep_dma_cyclic = sa11x0_dma_prep_dma_cyclic;
d->slave.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
d->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
d->slave.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES);
d->slave.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES);
ret = sa11x0_dma_init_dmadev(&d->slave, &pdev->dev); ret = sa11x0_dma_init_dmadev(&d->slave, &pdev->dev);
if (ret) { if (ret) {
dev_warn(d->slave.dev, "failed to register slave async device: %d\n", dev_warn(d->slave.dev, "failed to register slave async device: %d\n",
......
...@@ -51,12 +51,6 @@ config RCAR_HPB_DMAE ...@@ -51,12 +51,6 @@ config RCAR_HPB_DMAE
help help
Enable support for the Renesas R-Car series DMA controllers. Enable support for the Renesas R-Car series DMA controllers.
config RCAR_AUDMAC_PP
tristate "Renesas R-Car Audio DMAC Peripheral Peripheral support"
depends on SH_DMAE_BASE
help
Enable support for the Renesas R-Car Audio DMAC Peripheral Peripheral controllers.
config RCAR_DMAC config RCAR_DMAC
tristate "Renesas R-Car Gen2 DMA Controller" tristate "Renesas R-Car Gen2 DMA Controller"
depends on ARCH_SHMOBILE || COMPILE_TEST depends on ARCH_SHMOBILE || COMPILE_TEST
...@@ -64,3 +58,12 @@ config RCAR_DMAC ...@@ -64,3 +58,12 @@ config RCAR_DMAC
help help
This driver supports the general purpose DMA controller found in the This driver supports the general purpose DMA controller found in the
Renesas R-Car second generation SoCs. Renesas R-Car second generation SoCs.
config RENESAS_USB_DMAC
tristate "Renesas USB-DMA Controller"
depends on ARCH_SHMOBILE || COMPILE_TEST
select RENESAS_DMA
select DMA_VIRTUAL_CHANNELS
help
This driver supports the USB-DMA controller found in the Renesas
SoCs.
...@@ -15,5 +15,5 @@ obj-$(CONFIG_SH_DMAE) += shdma.o ...@@ -15,5 +15,5 @@ obj-$(CONFIG_SH_DMAE) += shdma.o
obj-$(CONFIG_SUDMAC) += sudmac.o obj-$(CONFIG_SUDMAC) += sudmac.o
obj-$(CONFIG_RCAR_HPB_DMAE) += rcar-hpbdma.o obj-$(CONFIG_RCAR_HPB_DMAE) += rcar-hpbdma.o
obj-$(CONFIG_RCAR_AUDMAC_PP) += rcar-audmapp.o
obj-$(CONFIG_RCAR_DMAC) += rcar-dmac.o obj-$(CONFIG_RCAR_DMAC) += rcar-dmac.o
obj-$(CONFIG_RENESAS_USB_DMAC) += usb-dmac.o
/*
* This is for Renesas R-Car Audio-DMAC-peri-peri.
*
* Copyright (C) 2014 Renesas Electronics Corporation
* Copyright (C) 2014 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* based on the drivers/dma/sh/shdma.c
*
* Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
* Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
* Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
*
* This 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; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
#include <linux/of_dma.h>
#include <linux/platform_data/dma-rcar-audmapp.h>
#include <linux/platform_device.h>
#include <linux/shdma-base.h>
/*
* DMA register
*/
#define PDMASAR 0x00
#define PDMADAR 0x04
#define PDMACHCR 0x0c
/* PDMACHCR */
#define PDMACHCR_DE (1 << 0)
#define AUDMAPP_MAX_CHANNELS 29
/* Default MEMCPY transfer size = 2^2 = 4 bytes */
#define LOG2_DEFAULT_XFER_SIZE 2
#define AUDMAPP_SLAVE_NUMBER 256
#define AUDMAPP_LEN_MAX (16 * 1024 * 1024)
struct audmapp_chan {
struct shdma_chan shdma_chan;
void __iomem *base;
dma_addr_t slave_addr;
u32 chcr;
};
struct audmapp_device {
struct shdma_dev shdma_dev;
struct audmapp_pdata *pdata;
struct device *dev;
void __iomem *chan_reg;
};
struct audmapp_desc {
struct shdma_desc shdma_desc;
dma_addr_t src;
dma_addr_t dst;
};
#define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan)
#define to_chan(chan) container_of(chan, struct audmapp_chan, shdma_chan)
#define to_desc(sdesc) container_of(sdesc, struct audmapp_desc, shdma_desc)
#define to_dev(chan) container_of(chan->shdma_chan.dma_chan.device, \
struct audmapp_device, shdma_dev.dma_dev)
static void audmapp_write(struct audmapp_chan *auchan, u32 data, u32 reg)
{
struct audmapp_device *audev = to_dev(auchan);
struct device *dev = audev->dev;
dev_dbg(dev, "w %p : %08x\n", auchan->base + reg, data);
iowrite32(data, auchan->base + reg);
}
static u32 audmapp_read(struct audmapp_chan *auchan, u32 reg)
{
return ioread32(auchan->base + reg);
}
static void audmapp_halt(struct shdma_chan *schan)
{
struct audmapp_chan *auchan = to_chan(schan);
int i;
audmapp_write(auchan, 0, PDMACHCR);
for (i = 0; i < 1024; i++) {
if (0 == audmapp_read(auchan, PDMACHCR))
return;
udelay(1);
}
}
static void audmapp_start_xfer(struct shdma_chan *schan,
struct shdma_desc *sdesc)
{
struct audmapp_chan *auchan = to_chan(schan);
struct audmapp_device *audev = to_dev(auchan);
struct audmapp_desc *desc = to_desc(sdesc);
struct device *dev = audev->dev;
u32 chcr = auchan->chcr | PDMACHCR_DE;
dev_dbg(dev, "src/dst/chcr = %pad/%pad/%08x\n",
&desc->src, &desc->dst, chcr);
audmapp_write(auchan, desc->src, PDMASAR);
audmapp_write(auchan, desc->dst, PDMADAR);
audmapp_write(auchan, chcr, PDMACHCR);
}
static int audmapp_get_config(struct audmapp_chan *auchan, int slave_id,
u32 *chcr, dma_addr_t *dst)
{
struct audmapp_device *audev = to_dev(auchan);
struct audmapp_pdata *pdata = audev->pdata;
struct audmapp_slave_config *cfg;
int i;
*chcr = 0;
*dst = 0;
if (!pdata) { /* DT */
*chcr = ((u32)slave_id) << 16;
auchan->shdma_chan.slave_id = (slave_id) >> 8;
return 0;
}
/* non-DT */
if (slave_id >= AUDMAPP_SLAVE_NUMBER)
return -ENXIO;
for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
if (cfg->slave_id == slave_id) {
*chcr = cfg->chcr;
*dst = cfg->dst;
return 0;
}
return -ENXIO;
}
static int audmapp_set_slave(struct shdma_chan *schan, int slave_id,
dma_addr_t slave_addr, bool try)
{
struct audmapp_chan *auchan = to_chan(schan);
u32 chcr;
dma_addr_t dst;
int ret;
ret = audmapp_get_config(auchan, slave_id, &chcr, &dst);
if (ret < 0)
return ret;
if (try)
return 0;
auchan->chcr = chcr;
auchan->slave_addr = slave_addr ? : dst;
return 0;
}
static int audmapp_desc_setup(struct shdma_chan *schan,
struct shdma_desc *sdesc,
dma_addr_t src, dma_addr_t dst, size_t *len)
{
struct audmapp_desc *desc = to_desc(sdesc);
if (*len > (size_t)AUDMAPP_LEN_MAX)
*len = (size_t)AUDMAPP_LEN_MAX;
desc->src = src;
desc->dst = dst;
return 0;
}
static void audmapp_setup_xfer(struct shdma_chan *schan,
int slave_id)
{
}
static dma_addr_t audmapp_slave_addr(struct shdma_chan *schan)
{
struct audmapp_chan *auchan = to_chan(schan);
return auchan->slave_addr;
}
static bool audmapp_channel_busy(struct shdma_chan *schan)
{
struct audmapp_chan *auchan = to_chan(schan);
u32 chcr = audmapp_read(auchan, PDMACHCR);
return chcr & ~PDMACHCR_DE;
}
static bool audmapp_desc_completed(struct shdma_chan *schan,
struct shdma_desc *sdesc)
{
return true;
}
static struct shdma_desc *audmapp_embedded_desc(void *buf, int i)
{
return &((struct audmapp_desc *)buf)[i].shdma_desc;
}
static const struct shdma_ops audmapp_shdma_ops = {
.halt_channel = audmapp_halt,
.desc_setup = audmapp_desc_setup,
.set_slave = audmapp_set_slave,
.start_xfer = audmapp_start_xfer,
.embedded_desc = audmapp_embedded_desc,
.setup_xfer = audmapp_setup_xfer,
.slave_addr = audmapp_slave_addr,
.channel_busy = audmapp_channel_busy,
.desc_completed = audmapp_desc_completed,
};
static int audmapp_chan_probe(struct platform_device *pdev,
struct audmapp_device *audev, int id)
{
struct shdma_dev *sdev = &audev->shdma_dev;
struct audmapp_chan *auchan;
struct shdma_chan *schan;
struct device *dev = audev->dev;
auchan = devm_kzalloc(dev, sizeof(*auchan), GFP_KERNEL);
if (!auchan)
return -ENOMEM;
schan = &auchan->shdma_chan;
schan->max_xfer_len = AUDMAPP_LEN_MAX;
shdma_chan_probe(sdev, schan, id);
auchan->base = audev->chan_reg + 0x20 + (0x10 * id);
dev_dbg(dev, "%02d : %p / %p", id, auchan->base, audev->chan_reg);
return 0;
}
static void audmapp_chan_remove(struct audmapp_device *audev)
{
struct shdma_chan *schan;
int i;
shdma_for_each_chan(schan, &audev->shdma_dev, i) {
BUG_ON(!schan);
shdma_chan_remove(schan);
}
}
static struct dma_chan *audmapp_of_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma)
{
dma_cap_mask_t mask;
struct dma_chan *chan;
u32 chcr = dma_spec->args[0];
if (dma_spec->args_count != 1)
return NULL;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
chan = dma_request_channel(mask, shdma_chan_filter, NULL);
if (chan)
to_shdma_chan(chan)->hw_req = chcr;
return chan;
}
static int audmapp_probe(struct platform_device *pdev)
{
struct audmapp_pdata *pdata = pdev->dev.platform_data;
struct device_node *np = pdev->dev.of_node;
struct audmapp_device *audev;
struct shdma_dev *sdev;
struct dma_device *dma_dev;
struct resource *res;
int err, i;
if (np)
of_dma_controller_register(np, audmapp_of_xlate, pdev);
else if (!pdata)
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
audev = devm_kzalloc(&pdev->dev, sizeof(*audev), GFP_KERNEL);
if (!audev)
return -ENOMEM;
audev->dev = &pdev->dev;
audev->pdata = pdata;
audev->chan_reg = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(audev->chan_reg))
return PTR_ERR(audev->chan_reg);
sdev = &audev->shdma_dev;
sdev->ops = &audmapp_shdma_ops;
sdev->desc_size = sizeof(struct audmapp_desc);
dma_dev = &sdev->dma_dev;
dma_dev->copy_align = LOG2_DEFAULT_XFER_SIZE;
dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
err = shdma_init(&pdev->dev, sdev, AUDMAPP_MAX_CHANNELS);
if (err < 0)
return err;
platform_set_drvdata(pdev, audev);
/* Create DMA Channel */
for (i = 0; i < AUDMAPP_MAX_CHANNELS; i++) {
err = audmapp_chan_probe(pdev, audev, i);
if (err)
goto chan_probe_err;
}
err = dma_async_device_register(dma_dev);
if (err < 0)
goto chan_probe_err;
return err;
chan_probe_err:
audmapp_chan_remove(audev);
shdma_cleanup(sdev);
return err;
}
static int audmapp_remove(struct platform_device *pdev)
{
struct audmapp_device *audev = platform_get_drvdata(pdev);
struct dma_device *dma_dev = &audev->shdma_dev.dma_dev;
dma_async_device_unregister(dma_dev);
audmapp_chan_remove(audev);
shdma_cleanup(&audev->shdma_dev);
return 0;
}
static const struct of_device_id audmapp_of_match[] = {
{ .compatible = "renesas,rcar-audmapp", },
{},
};
static struct platform_driver audmapp_driver = {
.probe = audmapp_probe,
.remove = audmapp_remove,
.driver = {
.name = "rcar-audmapp-engine",
.of_match_table = audmapp_of_match,
},
};
module_platform_driver(audmapp_driver);
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
MODULE_DESCRIPTION("Renesas R-Car Audio DMAC peri-peri driver");
MODULE_LICENSE("GPL");
...@@ -171,8 +171,7 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan) ...@@ -171,8 +171,7 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan)
return NULL; return NULL;
} }
static int shdma_setup_slave(struct shdma_chan *schan, int slave_id, static int shdma_setup_slave(struct shdma_chan *schan, dma_addr_t slave_addr)
dma_addr_t slave_addr)
{ {
struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
const struct shdma_ops *ops = sdev->ops; const struct shdma_ops *ops = sdev->ops;
...@@ -183,25 +182,23 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id, ...@@ -183,25 +182,23 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id,
ret = ops->set_slave(schan, match, slave_addr, true); ret = ops->set_slave(schan, match, slave_addr, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
slave_id = schan->slave_id;
} else { } else {
match = slave_id; match = schan->real_slave_id;
} }
if (slave_id < 0 || slave_id >= slave_num) if (schan->real_slave_id < 0 || schan->real_slave_id >= slave_num)
return -EINVAL; return -EINVAL;
if (test_and_set_bit(slave_id, shdma_slave_used)) if (test_and_set_bit(schan->real_slave_id, shdma_slave_used))
return -EBUSY; return -EBUSY;
ret = ops->set_slave(schan, match, slave_addr, false); ret = ops->set_slave(schan, match, slave_addr, false);
if (ret < 0) { if (ret < 0) {
clear_bit(slave_id, shdma_slave_used); clear_bit(schan->real_slave_id, shdma_slave_used);
return ret; return ret;
} }
schan->slave_id = slave_id; schan->slave_id = schan->real_slave_id;
return 0; return 0;
} }
...@@ -221,10 +218,12 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan) ...@@ -221,10 +218,12 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
*/ */
if (slave) { if (slave) {
/* Legacy mode: .private is set in filter */ /* Legacy mode: .private is set in filter */
ret = shdma_setup_slave(schan, slave->slave_id, 0); schan->real_slave_id = slave->slave_id;
ret = shdma_setup_slave(schan, 0);
if (ret < 0) if (ret < 0)
goto esetslave; goto esetslave;
} else { } else {
/* Normal mode: real_slave_id was set by filter */
schan->slave_id = -EINVAL; schan->slave_id = -EINVAL;
} }
...@@ -258,11 +257,14 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan) ...@@ -258,11 +257,14 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
/* /*
* This is the standard shdma filter function to be used as a replacement to the * This is the standard shdma filter function to be used as a replacement to the
* "old" method, using the .private pointer. If for some reason you allocate a * "old" method, using the .private pointer.
* channel without slave data, use something like ERR_PTR(-EINVAL) as a filter * You always have to pass a valid slave id as the argument, old drivers that
* pass ERR_PTR(-EINVAL) as a filter parameter and set it up in dma_slave_config
* need to be updated so we can remove the slave_id field from dma_slave_config.
* parameter. If this filter is used, the slave driver, after calling * parameter. If this filter is used, the slave driver, after calling
* dma_request_channel(), will also have to call dmaengine_slave_config() with * dma_request_channel(), will also have to call dmaengine_slave_config() with
* .slave_id, .direction, and either .src_addr or .dst_addr set. * .direction, and either .src_addr or .dst_addr set.
*
* NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
* capability! If this becomes a requirement, hardware glue drivers, using this * capability! If this becomes a requirement, hardware glue drivers, using this
* services would have to provide their own filters, which first would check * services would have to provide their own filters, which first would check
...@@ -276,7 +278,7 @@ bool shdma_chan_filter(struct dma_chan *chan, void *arg) ...@@ -276,7 +278,7 @@ bool shdma_chan_filter(struct dma_chan *chan, void *arg)
{ {
struct shdma_chan *schan; struct shdma_chan *schan;
struct shdma_dev *sdev; struct shdma_dev *sdev;
int match = (long)arg; int slave_id = (long)arg;
int ret; int ret;
/* Only support channels handled by this driver. */ /* Only support channels handled by this driver. */
...@@ -284,19 +286,39 @@ bool shdma_chan_filter(struct dma_chan *chan, void *arg) ...@@ -284,19 +286,39 @@ bool shdma_chan_filter(struct dma_chan *chan, void *arg)
shdma_alloc_chan_resources) shdma_alloc_chan_resources)
return false; return false;
if (match < 0) schan = to_shdma_chan(chan);
sdev = to_shdma_dev(chan->device);
/*
* For DT, the schan->slave_id field is generated by the
* set_slave function from the slave ID that is passed in
* from xlate. For the non-DT case, the slave ID is
* directly passed into the filter function by the driver
*/
if (schan->dev->of_node) {
ret = sdev->ops->set_slave(schan, slave_id, 0, true);
if (ret < 0)
return false;
schan->real_slave_id = schan->slave_id;
return true;
}
if (slave_id < 0) {
/* No slave requested - arbitrary channel */ /* No slave requested - arbitrary channel */
dev_warn(sdev->dma_dev.dev, "invalid slave ID passed to dma_request_slave\n");
return true; return true;
}
schan = to_shdma_chan(chan); if (slave_id >= slave_num)
if (!schan->dev->of_node && match >= slave_num)
return false; return false;
sdev = to_shdma_dev(schan->dma_chan.device); ret = sdev->ops->set_slave(schan, slave_id, 0, true);
ret = sdev->ops->set_slave(schan, match, 0, true);
if (ret < 0) if (ret < 0)
return false; return false;
schan->real_slave_id = slave_id;
return true; return true;
} }
EXPORT_SYMBOL(shdma_chan_filter); EXPORT_SYMBOL(shdma_chan_filter);
...@@ -452,6 +474,8 @@ static void shdma_free_chan_resources(struct dma_chan *chan) ...@@ -452,6 +474,8 @@ static void shdma_free_chan_resources(struct dma_chan *chan)
chan->private = NULL; chan->private = NULL;
} }
schan->real_slave_id = 0;
spin_lock_irq(&schan->chan_lock); spin_lock_irq(&schan->chan_lock);
list_splice_init(&schan->ld_free, &list); list_splice_init(&schan->ld_free, &list);
...@@ -764,11 +788,20 @@ static int shdma_config(struct dma_chan *chan, ...@@ -764,11 +788,20 @@ static int shdma_config(struct dma_chan *chan,
*/ */
if (!config) if (!config)
return -EINVAL; return -EINVAL;
/*
* overriding the slave_id through dma_slave_config is deprecated,
* but possibly some out-of-tree drivers still do it.
*/
if (WARN_ON_ONCE(config->slave_id &&
config->slave_id != schan->real_slave_id))
schan->real_slave_id = config->slave_id;
/* /*
* We could lock this, but you shouldn't be configuring the * We could lock this, but you shouldn't be configuring the
* channel, while using it... * channel, while using it...
*/ */
return shdma_setup_slave(schan, config->slave_id, return shdma_setup_slave(schan,
config->direction == DMA_DEV_TO_MEM ? config->direction == DMA_DEV_TO_MEM ?
config->src_addr : config->dst_addr); config->src_addr : config->dst_addr);
} }
......
...@@ -443,7 +443,7 @@ static bool sh_dmae_reset(struct sh_dmae_device *shdev) ...@@ -443,7 +443,7 @@ static bool sh_dmae_reset(struct sh_dmae_device *shdev)
return ret; return ret;
} }
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARM) #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
static irqreturn_t sh_dmae_err(int irq, void *data) static irqreturn_t sh_dmae_err(int irq, void *data)
{ {
struct sh_dmae_device *shdev = data; struct sh_dmae_device *shdev = data;
...@@ -689,7 +689,7 @@ static int sh_dmae_probe(struct platform_device *pdev) ...@@ -689,7 +689,7 @@ static int sh_dmae_probe(struct platform_device *pdev)
const struct sh_dmae_pdata *pdata; const struct sh_dmae_pdata *pdata;
unsigned long chan_flag[SH_DMAE_MAX_CHANNELS] = {}; unsigned long chan_flag[SH_DMAE_MAX_CHANNELS] = {};
int chan_irq[SH_DMAE_MAX_CHANNELS]; int chan_irq[SH_DMAE_MAX_CHANNELS];
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARM) #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
unsigned long irqflags = 0; unsigned long irqflags = 0;
int errirq; int errirq;
#endif #endif
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册