Commit 2ceedf97 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'dmaengine-4.13-rc1' of git://git.infradead.org/users/vkoul/slave-dma

Pull dmaengine updates from Vinod Koul:

 - removal of AVR32 support in dw driver as AVR32 is gone

 - new driver for Broadcom stream buffer accelerator (SBA) RAID driver

 - add support for Faraday Technology FTDMAC020 in amba-pl08x driver

 - IOMMU support in pl330 driver

 - updates to bunch of drivers

* tag 'dmaengine-4.13-rc1' of git://git.infradead.org/users/vkoul/slave-dma: (36 commits)
  dmaengine: qcom_hidma: correct API violation for submit
  dmaengine: zynqmp_dma: Remove max len check in zynqmp_dma_prep_memcpy
  dmaengine: tegra-apb: Really fix runtime-pm usage
  dmaengine: fsl_raid: make of_device_ids const.
  dmaengine: qcom_hidma: allow ACPI/DT parameters to be overridden
  dmaengine: fsldma: set BWC, DAHTS and SAHTS values correctly
  dmaengine: Kconfig: Simplify the help text for MXS_DMA
  dmaengine: pl330: Delete unused functions
  dmaengine: Replace WARN_TAINT_ONCE() with pr_warn_once()
  dmaengine: Kconfig: Extend the dependency for MXS_DMA
  dmaengine: mxs: Use %zu for printing a size_t variable
  dmaengine: ste_dma40: Cleanup scatterlist layering violations
  dmaengine: imx-dma: cleanup scatterlist layering violations
  dmaengine: use proper name for the R-Car SoC
  dmaengine: imx-sdma: Fix compilation warning.
  dmaengine: imx-sdma: Handle return value of clk_prepare_enable
  dmaengine: pl330: Add IOMMU support to slave tranfers
  dmaengine: DW DMAC: Handle return value of clk_prepare_enable
  dmaengine: pl08x: use GENMASK() to create bitmasks
  dmaengine: pl08x: Add support for Faraday Technology FTDMAC020
  ...
parents 09b56d5a 3edc8502
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
Required properties: Required properties:
- compatible: "arm,pl080", "arm,primecell"; - compatible: "arm,pl080", "arm,primecell";
"arm,pl081", "arm,primecell"; "arm,pl081", "arm,primecell";
"faraday,ftdmac020", "arm,primecell"
- arm,primecell-periphid: on the FTDMAC020 the primecell ID is not hard-coded
in the hardware and must be specified here as <0x0003b080>. This number
follows the PrimeCell standard numbering using the JEP106 vendor code 0x38
for Faraday Technology.
- reg: Address range of the PL08x registers - reg: Address range of the PL08x registers
- interrupt: The PL08x interrupt number - interrupt: The PL08x interrupt number
- clocks: The clock running the IP core clock - clocks: The clock running the IP core clock
...@@ -20,8 +25,8 @@ Optional properties: ...@@ -20,8 +25,8 @@ Optional properties:
- dma-requests: contains the total number of DMA requests supported by the DMAC - dma-requests: contains the total number of DMA requests supported by the DMAC
- memcpy-burst-size: the size of the bursts for memcpy: 1, 4, 8, 16, 32 - memcpy-burst-size: the size of the bursts for memcpy: 1, 4, 8, 16, 32
64, 128 or 256 bytes are legal values 64, 128 or 256 bytes are legal values
- memcpy-bus-width: the bus width used for memcpy: 8, 16 or 32 are legal - memcpy-bus-width: the bus width used for memcpy in bits: 8, 16 or 32 are legal
values values, the Faraday FTDMAC020 can also accept 64 bits
Clients Clients
Required properties: Required properties:
......
* Broadcom SBA RAID engine
Required properties:
- compatible: Should be one of the following
"brcm,iproc-sba"
"brcm,iproc-sba-v2"
The "brcm,iproc-sba" has support for only 6 PQ coefficients
The "brcm,iproc-sba-v2" has support for only 30 PQ coefficients
- mboxes: List of phandle and mailbox channel specifiers
Example:
raid_mbox: mbox@67400000 {
...
#mbox-cells = <3>;
...
};
raid0 {
compatible = "brcm,iproc-sba-v2";
mboxes = <&raid_mbox 0 0x1 0xffff>,
<&raid_mbox 1 0x1 0xffff>,
<&raid_mbox 2 0x1 0xffff>,
<&raid_mbox 3 0x1 0xffff>,
<&raid_mbox 4 0x1 0xffff>,
<&raid_mbox 5 0x1 0xffff>,
<&raid_mbox 6 0x1 0xffff>,
<&raid_mbox 7 0x1 0xffff>;
};
...@@ -30,8 +30,9 @@ Required Properties: ...@@ -30,8 +30,9 @@ Required Properties:
- interrupts: interrupt specifiers for the DMAC, one for each entry in - interrupts: interrupt specifiers for the DMAC, one for each entry in
interrupt-names. interrupt-names.
- interrupt-names: one entry per channel, named "ch%u", where %u is the - interrupt-names: one entry for the error interrupt, named "error", plus one
channel number ranging from zero to the number of channels minus one. entry per channel, named "ch%u", where %u is the channel number ranging from
zero to the number of channels minus one.
- clock-names: "fck" for the functional clock - clock-names: "fck" for the functional clock
- clocks: a list of phandle + clock-specifier pairs, one for each entry - clocks: a list of phandle + clock-specifier pairs, one for each entry
......
* SHDMA Device Tree bindings * SHDMA Device Tree bindings
Sh-/r-mobile and r-car systems often have multiple identical DMA controller Sh-/r-mobile and R-Car systems often have multiple identical DMA controller
instances, capable of serving any of a common set of DMA slave devices, using instances, capable of serving any of a common set of DMA slave devices, using
the same configuration. To describe this topology we require all compatible the same configuration. To describe this topology we require all compatible
SHDMA DT nodes to be placed under a DMA multiplexer node. All such compatible SHDMA DT nodes to be placed under a DMA multiplexer node. All such compatible
......
...@@ -137,6 +137,9 @@ static void pl08x_put_signal(const struct pl08x_channel_data *cd, int ch) ...@@ -137,6 +137,9 @@ static void pl08x_put_signal(const struct pl08x_channel_data *cd, int ch)
} }
static struct pl08x_platform_data pl08x_pd = { static struct pl08x_platform_data pl08x_pd = {
/* Some reasonable memcpy defaults */
.memcpy_burst_size = PL08X_BURST_SZ_256,
.memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
.slave_channels = &pl08x_slave_channels[0], .slave_channels = &pl08x_slave_channels[0],
.num_slave_channels = ARRAY_SIZE(pl08x_slave_channels), .num_slave_channels = ARRAY_SIZE(pl08x_slave_channels),
.get_xfer_signal = pl08x_get_signal, .get_xfer_signal = pl08x_get_signal,
......
...@@ -137,16 +137,10 @@ static const struct dma_slave_map s3c64xx_dma0_slave_map[] = { ...@@ -137,16 +137,10 @@ static const struct dma_slave_map s3c64xx_dma0_slave_map[] = {
}; };
struct pl08x_platform_data s3c64xx_dma0_plat_data = { struct pl08x_platform_data s3c64xx_dma0_plat_data = {
.memcpy_channel = { .memcpy_burst_size = PL08X_BURST_SZ_4,
.bus_id = "memcpy", .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
.cctl_memcpy = .memcpy_prot_buff = true,
(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT | .memcpy_prot_cache = true,
PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
PL080_CONTROL_PROT_SYS),
},
.lli_buses = PL08X_AHB1, .lli_buses = PL08X_AHB1,
.mem_buses = PL08X_AHB1, .mem_buses = PL08X_AHB1,
.get_xfer_signal = pl08x_get_xfer_signal, .get_xfer_signal = pl08x_get_xfer_signal,
...@@ -238,16 +232,10 @@ static const struct dma_slave_map s3c64xx_dma1_slave_map[] = { ...@@ -238,16 +232,10 @@ static const struct dma_slave_map s3c64xx_dma1_slave_map[] = {
}; };
struct pl08x_platform_data s3c64xx_dma1_plat_data = { struct pl08x_platform_data s3c64xx_dma1_plat_data = {
.memcpy_channel = { .memcpy_burst_size = PL08X_BURST_SZ_4,
.bus_id = "memcpy", .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
.cctl_memcpy = .memcpy_prot_buff = true,
(PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT | .memcpy_prot_cache = true,
PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
PL080_CONTROL_PROT_SYS),
},
.lli_buses = PL08X_AHB1, .lli_buses = PL08X_AHB1,
.mem_buses = PL08X_AHB1, .mem_buses = PL08X_AHB1,
.get_xfer_signal = pl08x_get_xfer_signal, .get_xfer_signal = pl08x_get_xfer_signal,
......
...@@ -44,16 +44,10 @@ struct pl022_ssp_controller pl022_plat_data = { ...@@ -44,16 +44,10 @@ struct pl022_ssp_controller pl022_plat_data = {
/* dmac device registration */ /* dmac device registration */
struct pl08x_platform_data pl080_plat_data = { struct pl08x_platform_data pl080_plat_data = {
.memcpy_channel = { .memcpy_burst_size = PL08X_BURST_SZ_16,
.bus_id = "memcpy", .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
.cctl_memcpy = .memcpy_prot_buff = true,
(PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \ .memcpy_prot_cache = true,
PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
PL080_CONTROL_PROT_SYS),
},
.lli_buses = PL08X_AHB1, .lli_buses = PL08X_AHB1,
.mem_buses = PL08X_AHB1, .mem_buses = PL08X_AHB1,
.get_xfer_signal = pl080_get_signal, .get_xfer_signal = pl080_get_signal,
......
...@@ -322,16 +322,10 @@ static struct pl08x_channel_data spear600_dma_info[] = { ...@@ -322,16 +322,10 @@ static struct pl08x_channel_data spear600_dma_info[] = {
}; };
static struct pl08x_platform_data spear6xx_pl080_plat_data = { static struct pl08x_platform_data spear6xx_pl080_plat_data = {
.memcpy_channel = { .memcpy_burst_size = PL08X_BURST_SZ_16,
.bus_id = "memcpy", .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS,
.cctl_memcpy = .memcpy_prot_buff = true,
(PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \ .memcpy_prot_cache = true,
PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
PL080_CONTROL_PROT_SYS),
},
.lli_buses = PL08X_AHB1, .lli_buses = PL08X_AHB1,
.mem_buses = PL08X_AHB1, .mem_buses = PL08X_AHB1,
.get_xfer_signal = pl080_get_signal, .get_xfer_signal = pl080_get_signal,
......
...@@ -62,9 +62,6 @@ do_async_gen_syndrome(struct dma_chan *chan, ...@@ -62,9 +62,6 @@ do_async_gen_syndrome(struct dma_chan *chan,
dma_addr_t dma_dest[2]; dma_addr_t dma_dest[2];
int src_off = 0; int src_off = 0;
if (submit->flags & ASYNC_TX_FENCE)
dma_flags |= DMA_PREP_FENCE;
while (src_cnt > 0) { while (src_cnt > 0) {
submit->flags = flags_orig; submit->flags = flags_orig;
pq_src_cnt = min(src_cnt, dma_maxpq(dma, dma_flags)); pq_src_cnt = min(src_cnt, dma_maxpq(dma, dma_flags));
...@@ -83,6 +80,8 @@ do_async_gen_syndrome(struct dma_chan *chan, ...@@ -83,6 +80,8 @@ do_async_gen_syndrome(struct dma_chan *chan,
if (cb_fn_orig) if (cb_fn_orig)
dma_flags |= DMA_PREP_INTERRUPT; dma_flags |= DMA_PREP_INTERRUPT;
} }
if (submit->flags & ASYNC_TX_FENCE)
dma_flags |= DMA_PREP_FENCE;
/* Drivers force forward progress in case they can not provide /* Drivers force forward progress in case they can not provide
* a descriptor * a descriptor
......
...@@ -62,8 +62,10 @@ config AMBA_PL08X ...@@ -62,8 +62,10 @@ config AMBA_PL08X
select DMA_ENGINE select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS select DMA_VIRTUAL_CHANNELS
help help
Platform has a PL08x DMAC device Say yes if your platform has a PL08x DMAC device which can
which can provide DMA engine support provide DMA engine support. This includes the original ARM
PL080 and PL081, Samsungs PL080 derivative and Faraday
Technology's FTDMAC020 PL080 derivative.
config AMCC_PPC440SPE_ADMA config AMCC_PPC440SPE_ADMA
tristate "AMCC PPC440SPe ADMA support" tristate "AMCC PPC440SPe ADMA support"
...@@ -99,6 +101,21 @@ config AXI_DMAC ...@@ -99,6 +101,21 @@ config AXI_DMAC
controller is often used in Analog Device's reference designs for FPGA controller is often used in Analog Device's reference designs for FPGA
platforms. platforms.
config BCM_SBA_RAID
tristate "Broadcom SBA RAID engine support"
depends on ARM64 || COMPILE_TEST
depends on MAILBOX && RAID6_PQ
select DMA_ENGINE
select DMA_ENGINE_RAID
select ASYNC_TX_DISABLE_XOR_VAL_DMA
select ASYNC_TX_DISABLE_PQ_VAL_DMA
default ARCH_BCM_IPROC
help
Enable support for Broadcom SBA RAID Engine. The SBA RAID
engine is available on most of the Broadcom iProc SoCs. It
has the capability to offload memcpy, xor and pq computation
for raid5/6.
config COH901318 config COH901318
bool "ST-Ericsson COH901318 DMA support" bool "ST-Ericsson COH901318 DMA support"
select DMA_ENGINE select DMA_ENGINE
...@@ -354,13 +371,12 @@ config MV_XOR_V2 ...@@ -354,13 +371,12 @@ config MV_XOR_V2
config MXS_DMA config MXS_DMA
bool "MXS DMA support" bool "MXS DMA support"
depends on SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q || SOC_IMX6UL depends on ARCH_MXS || ARCH_MXC || COMPILE_TEST
select STMP_DEVICE select STMP_DEVICE
select DMA_ENGINE select DMA_ENGINE
help help
Support the MXS DMA engine. This engine including APBH-DMA Support the MXS DMA engine. This engine including APBH-DMA
and APBX-DMA is integrated into Freescale and APBX-DMA is integrated into some Freescale chips.
i.MX23/28/MX6Q/MX6DL/MX6UL chips.
config MX3_IPU config MX3_IPU
bool "MX3x Image Processing Unit support" bool "MX3x Image Processing Unit support"
......
...@@ -17,6 +17,7 @@ obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/ ...@@ -17,6 +17,7 @@ obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
obj-$(CONFIG_AT_HDMAC) += at_hdmac.o obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
obj-$(CONFIG_AT_XDMAC) += at_xdmac.o obj-$(CONFIG_AT_XDMAC) += at_xdmac.o
obj-$(CONFIG_AXI_DMAC) += dma-axi-dmac.o obj-$(CONFIG_AXI_DMAC) += dma-axi-dmac.o
obj-$(CONFIG_BCM_SBA_RAID) += bcm-sba-raid.o
obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
obj-$(CONFIG_DMA_BCM2835) += bcm2835-dma.o obj-$(CONFIG_DMA_BCM2835) += bcm2835-dma.o
obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
......
This diff is collapsed.
This diff is collapsed.
...@@ -306,8 +306,12 @@ static int dw_resume_early(struct device *dev) ...@@ -306,8 +306,12 @@ static int dw_resume_early(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct dw_dma_chip *chip = platform_get_drvdata(pdev); struct dw_dma_chip *chip = platform_get_drvdata(pdev);
int ret;
ret = clk_prepare_enable(chip->clk);
if (ret)
return ret;
clk_prepare_enable(chip->clk);
return dw_dma_enable(chip); return dw_dma_enable(chip);
} }
......
...@@ -877,7 +877,7 @@ static int fsl_re_remove(struct platform_device *ofdev) ...@@ -877,7 +877,7 @@ static int fsl_re_remove(struct platform_device *ofdev)
return 0; return 0;
} }
static struct of_device_id fsl_re_ids[] = { static const struct of_device_id fsl_re_ids[] = {
{ .compatible = "fsl,raideng-v1.0", }, { .compatible = "fsl,raideng-v1.0", },
{} {}
}; };
......
...@@ -269,6 +269,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *chan, int size) ...@@ -269,6 +269,7 @@ static void fsl_chan_set_src_loop_size(struct fsldma_chan *chan, int size)
case 2: case 2:
case 4: case 4:
case 8: case 8:
mode &= ~FSL_DMA_MR_SAHTS_MASK;
mode |= FSL_DMA_MR_SAHE | (__ilog2(size) << 14); mode |= FSL_DMA_MR_SAHE | (__ilog2(size) << 14);
break; break;
} }
...@@ -301,6 +302,7 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *chan, int size) ...@@ -301,6 +302,7 @@ static void fsl_chan_set_dst_loop_size(struct fsldma_chan *chan, int size)
case 2: case 2:
case 4: case 4:
case 8: case 8:
mode &= ~FSL_DMA_MR_DAHTS_MASK;
mode |= FSL_DMA_MR_DAHE | (__ilog2(size) << 16); mode |= FSL_DMA_MR_DAHE | (__ilog2(size) << 16);
break; break;
} }
...@@ -327,7 +329,8 @@ static void fsl_chan_set_request_count(struct fsldma_chan *chan, int size) ...@@ -327,7 +329,8 @@ static void fsl_chan_set_request_count(struct fsldma_chan *chan, int size)
BUG_ON(size > 1024); BUG_ON(size > 1024);
mode = get_mr(chan); mode = get_mr(chan);
mode |= (__ilog2(size) << 24) & 0x0f000000; mode &= ~FSL_DMA_MR_BWC_MASK;
mode |= (__ilog2(size) << 24) & FSL_DMA_MR_BWC_MASK;
set_mr(chan, mode); set_mr(chan, mode);
} }
......
...@@ -36,6 +36,10 @@ ...@@ -36,6 +36,10 @@
#define FSL_DMA_MR_DAHE 0x00002000 #define FSL_DMA_MR_DAHE 0x00002000
#define FSL_DMA_MR_SAHE 0x00001000 #define FSL_DMA_MR_SAHE 0x00001000
#define FSL_DMA_MR_SAHTS_MASK 0x0000C000
#define FSL_DMA_MR_DAHTS_MASK 0x00030000
#define FSL_DMA_MR_BWC_MASK 0x0f000000
/* /*
* Bandwidth/pause control determines how many bytes a given * Bandwidth/pause control determines how many bytes a given
* channel is allowed to transfer before the DMA engine pauses * channel is allowed to transfer before the DMA engine pauses
......
...@@ -888,7 +888,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic( ...@@ -888,7 +888,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
sg_init_table(imxdmac->sg_list, periods); sg_init_table(imxdmac->sg_list, periods);
for (i = 0; i < periods; i++) { for (i = 0; i < periods; i++) {
imxdmac->sg_list[i].page_link = 0; sg_assign_page(&imxdmac->sg_list[i], NULL);
imxdmac->sg_list[i].offset = 0; imxdmac->sg_list[i].offset = 0;
imxdmac->sg_list[i].dma_address = dma_addr; imxdmac->sg_list[i].dma_address = dma_addr;
sg_dma_len(&imxdmac->sg_list[i]) = period_len; sg_dma_len(&imxdmac->sg_list[i]) = period_len;
...@@ -896,10 +896,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic( ...@@ -896,10 +896,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
} }
/* close the loop */ /* close the loop */
imxdmac->sg_list[periods].offset = 0; sg_chain(imxdmac->sg_list, periods + 1, imxdmac->sg_list);
sg_dma_len(&imxdmac->sg_list[periods]) = 0;
imxdmac->sg_list[periods].page_link =
((unsigned long)imxdmac->sg_list | 0x01) & ~0x02;
desc->type = IMXDMA_DESC_CYCLIC; desc->type = IMXDMA_DESC_CYCLIC;
desc->sg = imxdmac->sg_list; desc->sg = imxdmac->sg_list;
......
...@@ -1323,7 +1323,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( ...@@ -1323,7 +1323,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
} }
if (period_len > 0xffff) { if (period_len > 0xffff) {
dev_err(sdma->dev, "SDMA channel %d: maximum period size exceeded: %d > %d\n", dev_err(sdma->dev, "SDMA channel %d: maximum period size exceeded: %zu > %d\n",
channel, period_len, 0xffff); channel, period_len, 0xffff);
goto err_out; goto err_out;
} }
...@@ -1347,7 +1347,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( ...@@ -1347,7 +1347,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
if (i + 1 == num_periods) if (i + 1 == num_periods)
param |= BD_WRAP; param |= BD_WRAP;
dev_dbg(sdma->dev, "entry %d: count: %d dma: %#llx %s%s\n", dev_dbg(sdma->dev, "entry %d: count: %zu dma: %#llx %s%s\n",
i, period_len, (u64)dma_addr, i, period_len, (u64)dma_addr,
param & BD_WRAP ? "wrap" : "", param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : ""); param & BD_INTR ? " intr" : "");
...@@ -1755,19 +1755,26 @@ static int sdma_probe(struct platform_device *pdev) ...@@ -1755,19 +1755,26 @@ static int sdma_probe(struct platform_device *pdev)
if (IS_ERR(sdma->clk_ahb)) if (IS_ERR(sdma->clk_ahb))
return PTR_ERR(sdma->clk_ahb); return PTR_ERR(sdma->clk_ahb);
clk_prepare(sdma->clk_ipg); ret = clk_prepare(sdma->clk_ipg);
clk_prepare(sdma->clk_ahb); if (ret)
return ret;
ret = clk_prepare(sdma->clk_ahb);
if (ret)
goto err_clk;
ret = devm_request_irq(&pdev->dev, irq, sdma_int_handler, 0, "sdma", ret = devm_request_irq(&pdev->dev, irq, sdma_int_handler, 0, "sdma",
sdma); sdma);
if (ret) if (ret)
return ret; goto err_irq;
sdma->irq = irq; sdma->irq = irq;
sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL); sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL);
if (!sdma->script_addrs) if (!sdma->script_addrs) {
return -ENOMEM; ret = -ENOMEM;
goto err_irq;
}
/* initially no scripts available */ /* initially no scripts available */
saddr_arr = (s32 *)sdma->script_addrs; saddr_arr = (s32 *)sdma->script_addrs;
...@@ -1882,6 +1889,10 @@ static int sdma_probe(struct platform_device *pdev) ...@@ -1882,6 +1889,10 @@ static int sdma_probe(struct platform_device *pdev)
dma_async_device_unregister(&sdma->dma_device); dma_async_device_unregister(&sdma->dma_device);
err_init: err_init:
kfree(sdma->script_addrs); kfree(sdma->script_addrs);
err_irq:
clk_unprepare(sdma->clk_ahb);
err_clk:
clk_unprepare(sdma->clk_ipg);
return ret; return ret;
} }
...@@ -1893,6 +1904,8 @@ static int sdma_remove(struct platform_device *pdev) ...@@ -1893,6 +1904,8 @@ static int sdma_remove(struct platform_device *pdev)
devm_free_irq(&pdev->dev, sdma->irq, sdma); devm_free_irq(&pdev->dev, sdma->irq, sdma);
dma_async_device_unregister(&sdma->dma_device); dma_async_device_unregister(&sdma->dma_device);
kfree(sdma->script_addrs); kfree(sdma->script_addrs);
clk_unprepare(sdma->clk_ahb);
clk_unprepare(sdma->clk_ipg);
/* Kill the tasklet */ /* Kill the tasklet */
for (i = 0; i < MAX_DMA_CHANNELS; i++) { for (i = 0; i < MAX_DMA_CHANNELS; i++) {
struct sdma_channel *sdmac = &sdma->channel[i]; struct sdma_channel *sdmac = &sdma->channel[i];
......
...@@ -336,8 +336,8 @@ struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase) ...@@ -336,8 +336,8 @@ struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)
} }
if (dca3_tag_map_invalid(ioatdca->tag_map)) { if (dca3_tag_map_invalid(ioatdca->tag_map)) {
WARN_TAINT_ONCE(1, TAINT_FIRMWARE_WORKAROUND, add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
"%s %s: APICID_TAG_MAP set incorrectly by BIOS, disabling DCA\n", pr_warn_once("%s %s: APICID_TAG_MAP set incorrectly by BIOS, disabling DCA\n",
dev_driver_string(&pdev->dev), dev_driver_string(&pdev->dev),
dev_name(&pdev->dev)); dev_name(&pdev->dev));
free_dca_provider(dca); free_dca_provider(dca);
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#define MV_XOR_V2_DMA_IMSG_THRD_OFF 0x018 #define MV_XOR_V2_DMA_IMSG_THRD_OFF 0x018
#define MV_XOR_V2_DMA_IMSG_THRD_MASK 0x7FFF #define MV_XOR_V2_DMA_IMSG_THRD_MASK 0x7FFF
#define MV_XOR_V2_DMA_IMSG_THRD_SHIFT 0x0 #define MV_XOR_V2_DMA_IMSG_THRD_SHIFT 0x0
#define MV_XOR_V2_DMA_IMSG_TIMER_EN BIT(18)
#define MV_XOR_V2_DMA_DESQ_AWATTR_OFF 0x01C #define MV_XOR_V2_DMA_DESQ_AWATTR_OFF 0x01C
/* Same flags as MV_XOR_V2_DMA_DESQ_ARATTR_OFF */ /* Same flags as MV_XOR_V2_DMA_DESQ_ARATTR_OFF */
#define MV_XOR_V2_DMA_DESQ_ALLOC_OFF 0x04C #define MV_XOR_V2_DMA_DESQ_ALLOC_OFF 0x04C
...@@ -55,6 +56,9 @@ ...@@ -55,6 +56,9 @@
#define MV_XOR_V2_DMA_DESQ_STOP_OFF 0x800 #define MV_XOR_V2_DMA_DESQ_STOP_OFF 0x800
#define MV_XOR_V2_DMA_DESQ_DEALLOC_OFF 0x804 #define MV_XOR_V2_DMA_DESQ_DEALLOC_OFF 0x804
#define MV_XOR_V2_DMA_DESQ_ADD_OFF 0x808 #define MV_XOR_V2_DMA_DESQ_ADD_OFF 0x808
#define MV_XOR_V2_DMA_IMSG_TMOT 0x810
#define MV_XOR_V2_DMA_IMSG_TIMER_THRD_MASK 0x1FFF
#define MV_XOR_V2_DMA_IMSG_TIMER_THRD_SHIFT 0
/* XOR Global registers */ /* XOR Global registers */
#define MV_XOR_V2_GLOB_BW_CTRL 0x4 #define MV_XOR_V2_GLOB_BW_CTRL 0x4
...@@ -90,6 +94,13 @@ ...@@ -90,6 +94,13 @@
*/ */
#define MV_XOR_V2_DESC_NUM 1024 #define MV_XOR_V2_DESC_NUM 1024
/*
* Threshold values for descriptors and timeout, determined by
* experimentation as giving a good level of performance.
*/
#define MV_XOR_V2_DONE_IMSG_THRD 0x14
#define MV_XOR_V2_TIMER_THRD 0xB0
/** /**
* struct mv_xor_v2_descriptor - DMA HW descriptor * struct mv_xor_v2_descriptor - DMA HW descriptor
* @desc_id: used by S/W and is not affected by H/W. * @desc_id: used by S/W and is not affected by H/W.
...@@ -246,6 +257,29 @@ static int mv_xor_v2_set_desc_size(struct mv_xor_v2_device *xor_dev) ...@@ -246,6 +257,29 @@ static int mv_xor_v2_set_desc_size(struct mv_xor_v2_device *xor_dev)
return MV_XOR_V2_EXT_DESC_SIZE; return MV_XOR_V2_EXT_DESC_SIZE;
} }
/*
* Set the IMSG threshold
*/
static inline
void mv_xor_v2_enable_imsg_thrd(struct mv_xor_v2_device *xor_dev)
{
u32 reg;
/* Configure threshold of number of descriptors, and enable timer */
reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF);
reg &= (~MV_XOR_V2_DMA_IMSG_THRD_MASK << MV_XOR_V2_DMA_IMSG_THRD_SHIFT);
reg |= (MV_XOR_V2_DONE_IMSG_THRD << MV_XOR_V2_DMA_IMSG_THRD_SHIFT);
reg |= MV_XOR_V2_DMA_IMSG_TIMER_EN;
writel(reg, xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF);
/* Configure Timer Threshold */
reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_TMOT);
reg &= (~MV_XOR_V2_DMA_IMSG_TIMER_THRD_MASK <<
MV_XOR_V2_DMA_IMSG_TIMER_THRD_SHIFT);
reg |= (MV_XOR_V2_TIMER_THRD << MV_XOR_V2_DMA_IMSG_TIMER_THRD_SHIFT);
writel(reg, xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_TMOT);
}
static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data) static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data)
{ {
struct mv_xor_v2_device *xor_dev = data; struct mv_xor_v2_device *xor_dev = data;
...@@ -501,9 +535,6 @@ static void mv_xor_v2_issue_pending(struct dma_chan *chan) ...@@ -501,9 +535,6 @@ static void mv_xor_v2_issue_pending(struct dma_chan *chan)
mv_xor_v2_add_desc_to_desq(xor_dev, xor_dev->npendings); mv_xor_v2_add_desc_to_desq(xor_dev, xor_dev->npendings);
xor_dev->npendings = 0; xor_dev->npendings = 0;
/* Activate the channel */
writel(0, xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_STOP_OFF);
spin_unlock_bh(&xor_dev->lock); spin_unlock_bh(&xor_dev->lock);
} }
...@@ -665,6 +696,27 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev) ...@@ -665,6 +696,27 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev)
return 0; return 0;
} }
static int mv_xor_v2_suspend(struct platform_device *dev, pm_message_t state)
{
struct mv_xor_v2_device *xor_dev = platform_get_drvdata(dev);
/* Set this bit to disable to stop the XOR unit. */
writel(0x1, xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_STOP_OFF);
return 0;
}
static int mv_xor_v2_resume(struct platform_device *dev)
{
struct mv_xor_v2_device *xor_dev = platform_get_drvdata(dev);
mv_xor_v2_set_desc_size(xor_dev);
mv_xor_v2_enable_imsg_thrd(xor_dev);
mv_xor_v2_descq_init(xor_dev);
return 0;
}
static int mv_xor_v2_probe(struct platform_device *pdev) static int mv_xor_v2_probe(struct platform_device *pdev)
{ {
struct mv_xor_v2_device *xor_dev; struct mv_xor_v2_device *xor_dev;
...@@ -795,6 +847,8 @@ static int mv_xor_v2_probe(struct platform_device *pdev) ...@@ -795,6 +847,8 @@ static int mv_xor_v2_probe(struct platform_device *pdev)
list_add_tail(&xor_dev->dmachan.device_node, list_add_tail(&xor_dev->dmachan.device_node,
&dma_dev->channels); &dma_dev->channels);
mv_xor_v2_enable_imsg_thrd(xor_dev);
mv_xor_v2_descq_init(xor_dev); mv_xor_v2_descq_init(xor_dev);
ret = dma_async_device_register(dma_dev); ret = dma_async_device_register(dma_dev);
...@@ -844,6 +898,8 @@ MODULE_DEVICE_TABLE(of, mv_xor_v2_dt_ids); ...@@ -844,6 +898,8 @@ MODULE_DEVICE_TABLE(of, mv_xor_v2_dt_ids);
static struct platform_driver mv_xor_v2_driver = { static struct platform_driver mv_xor_v2_driver = {
.probe = mv_xor_v2_probe, .probe = mv_xor_v2_probe,
.suspend = mv_xor_v2_suspend,
.resume = mv_xor_v2_resume,
.remove = mv_xor_v2_remove, .remove = mv_xor_v2_remove,
.driver = { .driver = {
.name = "mv_xor_v2", .name = "mv_xor_v2",
......
...@@ -617,7 +617,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic( ...@@ -617,7 +617,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
if (period_len > MAX_XFER_BYTES) { if (period_len > MAX_XFER_BYTES) {
dev_err(mxs_dma->dma_device.dev, dev_err(mxs_dma->dma_device.dev,
"maximum period size exceeded: %d > %d\n", "maximum period size exceeded: %zu > %d\n",
period_len, MAX_XFER_BYTES); period_len, MAX_XFER_BYTES);
goto err_out; goto err_out;
} }
......
...@@ -443,7 +443,10 @@ struct dma_pl330_chan { ...@@ -443,7 +443,10 @@ struct dma_pl330_chan {
/* For D-to-M and M-to-D channels */ /* For D-to-M and M-to-D channels */
int burst_sz; /* the peripheral fifo width */ int burst_sz; /* the peripheral fifo width */
int burst_len; /* the number of burst */ int burst_len; /* the number of burst */
dma_addr_t fifo_addr; phys_addr_t fifo_addr;
/* DMA-mapped view of the FIFO; may differ if an IOMMU is present */
dma_addr_t fifo_dma;
enum dma_data_direction dir;
/* for cyclic capability */ /* for cyclic capability */
bool cyclic; bool cyclic;
...@@ -538,11 +541,6 @@ struct _xfer_spec { ...@@ -538,11 +541,6 @@ struct _xfer_spec {
struct dma_pl330_desc *desc; struct dma_pl330_desc *desc;
}; };
static inline bool _queue_empty(struct pl330_thread *thrd)
{
return thrd->req[0].desc == NULL && thrd->req[1].desc == NULL;
}
static inline bool _queue_full(struct pl330_thread *thrd) static inline bool _queue_full(struct pl330_thread *thrd)
{ {
return thrd->req[0].desc != NULL && thrd->req[1].desc != NULL; return thrd->req[0].desc != NULL && thrd->req[1].desc != NULL;
...@@ -564,23 +562,6 @@ static inline u32 get_revision(u32 periph_id) ...@@ -564,23 +562,6 @@ static inline u32 get_revision(u32 periph_id)
return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK; return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK;
} }
static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
enum pl330_dst da, u16 val)
{
if (dry_run)
return SZ_DMAADDH;
buf[0] = CMD_DMAADDH;
buf[0] |= (da << 1);
buf[1] = val;
buf[2] = val >> 8;
PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
da == 1 ? "DA" : "SA", val);
return SZ_DMAADDH;
}
static inline u32 _emit_END(unsigned dry_run, u8 buf[]) static inline u32 _emit_END(unsigned dry_run, u8 buf[])
{ {
if (dry_run) if (dry_run)
...@@ -738,18 +719,6 @@ static inline u32 _emit_MOV(unsigned dry_run, u8 buf[], ...@@ -738,18 +719,6 @@ static inline u32 _emit_MOV(unsigned dry_run, u8 buf[],
return SZ_DMAMOV; return SZ_DMAMOV;
} }
static inline u32 _emit_NOP(unsigned dry_run, u8 buf[])
{
if (dry_run)
return SZ_DMANOP;
buf[0] = CMD_DMANOP;
PL330_DBGCMD_DUMP(SZ_DMANOP, "\tDMANOP\n");
return SZ_DMANOP;
}
static inline u32 _emit_RMB(unsigned dry_run, u8 buf[]) static inline u32 _emit_RMB(unsigned dry_run, u8 buf[])
{ {
if (dry_run) if (dry_run)
...@@ -817,39 +786,6 @@ static inline u32 _emit_STP(unsigned dry_run, u8 buf[], ...@@ -817,39 +786,6 @@ static inline u32 _emit_STP(unsigned dry_run, u8 buf[],
return SZ_DMASTP; return SZ_DMASTP;
} }
static inline u32 _emit_STZ(unsigned dry_run, u8 buf[])
{
if (dry_run)
return SZ_DMASTZ;
buf[0] = CMD_DMASTZ;
PL330_DBGCMD_DUMP(SZ_DMASTZ, "\tDMASTZ\n");
return SZ_DMASTZ;
}
static inline u32 _emit_WFE(unsigned dry_run, u8 buf[], u8 ev,
unsigned invalidate)
{
if (dry_run)
return SZ_DMAWFE;
buf[0] = CMD_DMAWFE;
ev &= 0x1f;
ev <<= 3;
buf[1] = ev;
if (invalidate)
buf[1] |= (1 << 1);
PL330_DBGCMD_DUMP(SZ_DMAWFE, "\tDMAWFE %u%s\n",
ev >> 3, invalidate ? ", I" : "");
return SZ_DMAWFE;
}
static inline u32 _emit_WFP(unsigned dry_run, u8 buf[], static inline u32 _emit_WFP(unsigned dry_run, u8 buf[],
enum pl330_cond cond, u8 peri) enum pl330_cond cond, u8 peri)
{ {
...@@ -2120,11 +2056,60 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan) ...@@ -2120,11 +2056,60 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
return 1; return 1;
} }
/*
* We need the data direction between the DMAC (the dma-mapping "device") and
* the FIFO (the dmaengine "dev"), from the FIFO's point of view. Confusing!
*/
static enum dma_data_direction
pl330_dma_slave_map_dir(enum dma_transfer_direction dir)
{
switch (dir) {
case DMA_MEM_TO_DEV:
return DMA_FROM_DEVICE;
case DMA_DEV_TO_MEM:
return DMA_TO_DEVICE;
case DMA_DEV_TO_DEV:
return DMA_BIDIRECTIONAL;
default:
return DMA_NONE;
}
}
static void pl330_unprep_slave_fifo(struct dma_pl330_chan *pch)
{
if (pch->dir != DMA_NONE)
dma_unmap_resource(pch->chan.device->dev, pch->fifo_dma,
1 << pch->burst_sz, pch->dir, 0);
pch->dir = DMA_NONE;
}
static bool pl330_prep_slave_fifo(struct dma_pl330_chan *pch,
enum dma_transfer_direction dir)
{
struct device *dev = pch->chan.device->dev;
enum dma_data_direction dma_dir = pl330_dma_slave_map_dir(dir);
/* Already mapped for this config? */
if (pch->dir == dma_dir)
return true;
pl330_unprep_slave_fifo(pch);
pch->fifo_dma = dma_map_resource(dev, pch->fifo_addr,
1 << pch->burst_sz, dma_dir, 0);
if (dma_mapping_error(dev, pch->fifo_dma))
return false;
pch->dir = dma_dir;
return true;
}
static int pl330_config(struct dma_chan *chan, static int pl330_config(struct dma_chan *chan,
struct dma_slave_config *slave_config) struct dma_slave_config *slave_config)
{ {
struct dma_pl330_chan *pch = to_pchan(chan); struct dma_pl330_chan *pch = to_pchan(chan);
pl330_unprep_slave_fifo(pch);
if (slave_config->direction == DMA_MEM_TO_DEV) { if (slave_config->direction == DMA_MEM_TO_DEV) {
if (slave_config->dst_addr) if (slave_config->dst_addr)
pch->fifo_addr = slave_config->dst_addr; pch->fifo_addr = slave_config->dst_addr;
...@@ -2235,6 +2220,7 @@ static void pl330_free_chan_resources(struct dma_chan *chan) ...@@ -2235,6 +2220,7 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
spin_unlock_irqrestore(&pl330->lock, flags); spin_unlock_irqrestore(&pl330->lock, flags);
pm_runtime_mark_last_busy(pch->dmac->ddma.dev); pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
pm_runtime_put_autosuspend(pch->dmac->ddma.dev); pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
pl330_unprep_slave_fifo(pch);
} }
static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch, static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch,
...@@ -2564,6 +2550,9 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( ...@@ -2564,6 +2550,9 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
return NULL; return NULL;
} }
if (!pl330_prep_slave_fifo(pch, direction))
return NULL;
for (i = 0; i < len / period_len; i++) { for (i = 0; i < len / period_len; i++) {
desc = pl330_get_desc(pch); desc = pl330_get_desc(pch);
if (!desc) { if (!desc) {
...@@ -2593,12 +2582,12 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( ...@@ -2593,12 +2582,12 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
desc->rqcfg.src_inc = 1; desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 0; desc->rqcfg.dst_inc = 0;
src = dma_addr; src = dma_addr;
dst = pch->fifo_addr; dst = pch->fifo_dma;
break; break;
case DMA_DEV_TO_MEM: case DMA_DEV_TO_MEM:
desc->rqcfg.src_inc = 0; desc->rqcfg.src_inc = 0;
desc->rqcfg.dst_inc = 1; desc->rqcfg.dst_inc = 1;
src = pch->fifo_addr; src = pch->fifo_dma;
dst = dma_addr; dst = dma_addr;
break; break;
default: default:
...@@ -2711,12 +2700,12 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ...@@ -2711,12 +2700,12 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
struct dma_pl330_chan *pch = to_pchan(chan); struct dma_pl330_chan *pch = to_pchan(chan);
struct scatterlist *sg; struct scatterlist *sg;
int i; int i;
dma_addr_t addr;
if (unlikely(!pch || !sgl || !sg_len)) if (unlikely(!pch || !sgl || !sg_len))
return NULL; return NULL;
addr = pch->fifo_addr; if (!pl330_prep_slave_fifo(pch, direction))
return NULL;
first = NULL; first = NULL;
...@@ -2742,13 +2731,13 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ...@@ -2742,13 +2731,13 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
if (direction == DMA_MEM_TO_DEV) { if (direction == DMA_MEM_TO_DEV) {
desc->rqcfg.src_inc = 1; desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 0; desc->rqcfg.dst_inc = 0;
fill_px(&desc->px, fill_px(&desc->px, pch->fifo_dma, sg_dma_address(sg),
addr, sg_dma_address(sg), sg_dma_len(sg)); sg_dma_len(sg));
} else { } else {
desc->rqcfg.src_inc = 0; desc->rqcfg.src_inc = 0;
desc->rqcfg.dst_inc = 1; desc->rqcfg.dst_inc = 1;
fill_px(&desc->px, fill_px(&desc->px, sg_dma_address(sg), pch->fifo_dma,
sg_dma_address(sg), addr, sg_dma_len(sg)); sg_dma_len(sg));
} }
desc->rqcfg.brst_size = pch->burst_sz; desc->rqcfg.brst_size = pch->burst_sz;
...@@ -2906,6 +2895,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2906,6 +2895,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
pch->thread = NULL; pch->thread = NULL;
pch->chan.device = pd; pch->chan.device = pd;
pch->dmac = pl330; pch->dmac = pl330;
pch->dir = DMA_NONE;
/* Add the channel to the DMAC list */ /* Add the channel to the DMAC list */
list_add_tail(&pch->chan.device_node, &pd->channels); list_add_tail(&pch->chan.device_node, &pd->channels);
......
/* /*
* Qualcomm Technologies HIDMA DMA engine interface * Qualcomm Technologies HIDMA DMA engine interface
* *
* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
...@@ -210,6 +210,7 @@ static int hidma_chan_init(struct hidma_dev *dmadev, u32 dma_sig) ...@@ -210,6 +210,7 @@ static int hidma_chan_init(struct hidma_dev *dmadev, u32 dma_sig)
INIT_LIST_HEAD(&mchan->prepared); INIT_LIST_HEAD(&mchan->prepared);
INIT_LIST_HEAD(&mchan->active); INIT_LIST_HEAD(&mchan->active);
INIT_LIST_HEAD(&mchan->completed); INIT_LIST_HEAD(&mchan->completed);
INIT_LIST_HEAD(&mchan->queued);
spin_lock_init(&mchan->lock); spin_lock_init(&mchan->lock);
list_add_tail(&mchan->chan.device_node, &ddev->channels); list_add_tail(&mchan->chan.device_node, &ddev->channels);
...@@ -230,9 +231,15 @@ static void hidma_issue_pending(struct dma_chan *dmach) ...@@ -230,9 +231,15 @@ static void hidma_issue_pending(struct dma_chan *dmach)
struct hidma_chan *mchan = to_hidma_chan(dmach); struct hidma_chan *mchan = to_hidma_chan(dmach);
struct hidma_dev *dmadev = mchan->dmadev; struct hidma_dev *dmadev = mchan->dmadev;
unsigned long flags; unsigned long flags;
struct hidma_desc *qdesc, *next;
int status; int status;
spin_lock_irqsave(&mchan->lock, flags); spin_lock_irqsave(&mchan->lock, flags);
list_for_each_entry_safe(qdesc, next, &mchan->queued, node) {
hidma_ll_queue_request(dmadev->lldev, qdesc->tre_ch);
list_move_tail(&qdesc->node, &mchan->active);
}
if (!mchan->running) { if (!mchan->running) {
struct hidma_desc *desc = list_first_entry(&mchan->active, struct hidma_desc *desc = list_first_entry(&mchan->active,
struct hidma_desc, struct hidma_desc,
...@@ -315,17 +322,18 @@ static dma_cookie_t hidma_tx_submit(struct dma_async_tx_descriptor *txd) ...@@ -315,17 +322,18 @@ static dma_cookie_t hidma_tx_submit(struct dma_async_tx_descriptor *txd)
pm_runtime_put_autosuspend(dmadev->ddev.dev); pm_runtime_put_autosuspend(dmadev->ddev.dev);
return -ENODEV; return -ENODEV;
} }
pm_runtime_mark_last_busy(dmadev->ddev.dev);
pm_runtime_put_autosuspend(dmadev->ddev.dev);
mdesc = container_of(txd, struct hidma_desc, desc); mdesc = container_of(txd, struct hidma_desc, desc);
spin_lock_irqsave(&mchan->lock, irqflags); spin_lock_irqsave(&mchan->lock, irqflags);
/* Move descriptor to active */ /* Move descriptor to queued */
list_move_tail(&mdesc->node, &mchan->active); list_move_tail(&mdesc->node, &mchan->queued);
/* Update cookie */ /* Update cookie */
cookie = dma_cookie_assign(txd); cookie = dma_cookie_assign(txd);
hidma_ll_queue_request(dmadev->lldev, mdesc->tre_ch);
spin_unlock_irqrestore(&mchan->lock, irqflags); spin_unlock_irqrestore(&mchan->lock, irqflags);
return cookie; return cookie;
...@@ -431,6 +439,7 @@ static int hidma_terminate_channel(struct dma_chan *chan) ...@@ -431,6 +439,7 @@ static int hidma_terminate_channel(struct dma_chan *chan)
list_splice_init(&mchan->active, &list); list_splice_init(&mchan->active, &list);
list_splice_init(&mchan->prepared, &list); list_splice_init(&mchan->prepared, &list);
list_splice_init(&mchan->completed, &list); list_splice_init(&mchan->completed, &list);
list_splice_init(&mchan->queued, &list);
spin_unlock_irqrestore(&mchan->lock, irqflags); spin_unlock_irqrestore(&mchan->lock, irqflags);
/* this suspends the existing transfer */ /* this suspends the existing transfer */
...@@ -795,8 +804,11 @@ static int hidma_probe(struct platform_device *pdev) ...@@ -795,8 +804,11 @@ static int hidma_probe(struct platform_device *pdev)
device_property_read_u32(&pdev->dev, "desc-count", device_property_read_u32(&pdev->dev, "desc-count",
&dmadev->nr_descriptors); &dmadev->nr_descriptors);
if (!dmadev->nr_descriptors && nr_desc_prm) if (nr_desc_prm) {
dev_info(&pdev->dev, "overriding number of descriptors as %d\n",
nr_desc_prm);
dmadev->nr_descriptors = nr_desc_prm; dmadev->nr_descriptors = nr_desc_prm;
}
if (!dmadev->nr_descriptors) if (!dmadev->nr_descriptors)
dmadev->nr_descriptors = HIDMA_NR_DEFAULT_DESC; dmadev->nr_descriptors = HIDMA_NR_DEFAULT_DESC;
......
...@@ -104,6 +104,7 @@ struct hidma_chan { ...@@ -104,6 +104,7 @@ struct hidma_chan {
struct dma_chan chan; struct dma_chan chan;
struct list_head free; struct list_head free;
struct list_head prepared; struct list_head prepared;
struct list_head queued;
struct list_head active; struct list_head active;
struct list_head completed; struct list_head completed;
......
/* /*
* Qualcomm Technologies HIDMA DMA engine Management interface * Qualcomm Technologies HIDMA DMA engine Management interface
* *
* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
...@@ -49,6 +49,26 @@ ...@@ -49,6 +49,26 @@
#define HIDMA_AUTOSUSPEND_TIMEOUT 2000 #define HIDMA_AUTOSUSPEND_TIMEOUT 2000
#define HIDMA_MAX_CHANNEL_WEIGHT 15 #define HIDMA_MAX_CHANNEL_WEIGHT 15
static unsigned int max_write_request;
module_param(max_write_request, uint, 0644);
MODULE_PARM_DESC(max_write_request,
"maximum write burst (default: ACPI/DT value)");
static unsigned int max_read_request;
module_param(max_read_request, uint, 0644);
MODULE_PARM_DESC(max_read_request,
"maximum read burst (default: ACPI/DT value)");
static unsigned int max_wr_xactions;
module_param(max_wr_xactions, uint, 0644);
MODULE_PARM_DESC(max_wr_xactions,
"maximum number of write transactions (default: ACPI/DT value)");
static unsigned int max_rd_xactions;
module_param(max_rd_xactions, uint, 0644);
MODULE_PARM_DESC(max_rd_xactions,
"maximum number of read transactions (default: ACPI/DT value)");
int hidma_mgmt_setup(struct hidma_mgmt_dev *mgmtdev) int hidma_mgmt_setup(struct hidma_mgmt_dev *mgmtdev)
{ {
unsigned int i; unsigned int i;
...@@ -207,12 +227,25 @@ static int hidma_mgmt_probe(struct platform_device *pdev) ...@@ -207,12 +227,25 @@ static int hidma_mgmt_probe(struct platform_device *pdev)
goto out; goto out;
} }
if (max_write_request) {
dev_info(&pdev->dev, "overriding max-write-burst-bytes: %d\n",
max_write_request);
mgmtdev->max_write_request = max_write_request;
} else
max_write_request = mgmtdev->max_write_request;
rc = device_property_read_u32(&pdev->dev, "max-read-burst-bytes", rc = device_property_read_u32(&pdev->dev, "max-read-burst-bytes",
&mgmtdev->max_read_request); &mgmtdev->max_read_request);
if (rc) { if (rc) {
dev_err(&pdev->dev, "max-read-burst-bytes missing\n"); dev_err(&pdev->dev, "max-read-burst-bytes missing\n");
goto out; goto out;
} }
if (max_read_request) {
dev_info(&pdev->dev, "overriding max-read-burst-bytes: %d\n",
max_read_request);
mgmtdev->max_read_request = max_read_request;
} else
max_read_request = mgmtdev->max_read_request;
rc = device_property_read_u32(&pdev->dev, "max-write-transactions", rc = device_property_read_u32(&pdev->dev, "max-write-transactions",
&mgmtdev->max_wr_xactions); &mgmtdev->max_wr_xactions);
...@@ -220,6 +253,12 @@ static int hidma_mgmt_probe(struct platform_device *pdev) ...@@ -220,6 +253,12 @@ static int hidma_mgmt_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "max-write-transactions missing\n"); dev_err(&pdev->dev, "max-write-transactions missing\n");
goto out; goto out;
} }
if (max_wr_xactions) {
dev_info(&pdev->dev, "overriding max-write-transactions: %d\n",
max_wr_xactions);
mgmtdev->max_wr_xactions = max_wr_xactions;
} else
max_wr_xactions = mgmtdev->max_wr_xactions;
rc = device_property_read_u32(&pdev->dev, "max-read-transactions", rc = device_property_read_u32(&pdev->dev, "max-read-transactions",
&mgmtdev->max_rd_xactions); &mgmtdev->max_rd_xactions);
...@@ -227,6 +266,12 @@ static int hidma_mgmt_probe(struct platform_device *pdev) ...@@ -227,6 +266,12 @@ static int hidma_mgmt_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "max-read-transactions missing\n"); dev_err(&pdev->dev, "max-read-transactions missing\n");
goto out; goto out;
} }
if (max_rd_xactions) {
dev_info(&pdev->dev, "overriding max-read-transactions: %d\n",
max_rd_xactions);
mgmtdev->max_rd_xactions = max_rd_xactions;
} else
max_rd_xactions = mgmtdev->max_rd_xactions;
mgmtdev->priority = devm_kcalloc(&pdev->dev, mgmtdev->priority = devm_kcalloc(&pdev->dev,
mgmtdev->dma_channels, mgmtdev->dma_channels,
......
...@@ -144,6 +144,7 @@ struct rcar_dmac_chan_map { ...@@ -144,6 +144,7 @@ struct rcar_dmac_chan_map {
* @chan: base DMA channel object * @chan: base DMA channel object
* @iomem: channel I/O memory base * @iomem: channel I/O memory base
* @index: index of this channel in the controller * @index: index of this channel in the controller
* @irq: channel IRQ
* @src: slave memory address and size on the source side * @src: slave memory address and size on the source side
* @dst: slave memory address and size on the destination side * @dst: slave memory address and size on the destination side
* @mid_rid: hardware MID/RID for the DMA client using this channel * @mid_rid: hardware MID/RID for the DMA client using this channel
...@@ -161,6 +162,7 @@ struct rcar_dmac_chan { ...@@ -161,6 +162,7 @@ struct rcar_dmac_chan {
struct dma_chan chan; struct dma_chan chan;
void __iomem *iomem; void __iomem *iomem;
unsigned int index; unsigned int index;
int irq;
struct rcar_dmac_chan_slave src; struct rcar_dmac_chan_slave src;
struct rcar_dmac_chan_slave dst; struct rcar_dmac_chan_slave dst;
...@@ -1008,7 +1010,11 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan) ...@@ -1008,7 +1010,11 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan)
rcar_dmac_chan_halt(rchan); rcar_dmac_chan_halt(rchan);
spin_unlock_irq(&rchan->lock); spin_unlock_irq(&rchan->lock);
/* Now no new interrupts will occur */ /*
* Now no new interrupts will occur, but one might already be
* running. Wait for it to finish before freeing resources.
*/
synchronize_irq(rchan->irq);
if (rchan->mid_rid >= 0) { if (rchan->mid_rid >= 0) {
/* The caller is holding dma_list_mutex */ /* The caller is holding dma_list_mutex */
...@@ -1366,6 +1372,13 @@ static void rcar_dmac_issue_pending(struct dma_chan *chan) ...@@ -1366,6 +1372,13 @@ static void rcar_dmac_issue_pending(struct dma_chan *chan)
spin_unlock_irqrestore(&rchan->lock, flags); spin_unlock_irqrestore(&rchan->lock, flags);
} }
static void rcar_dmac_device_synchronize(struct dma_chan *chan)
{
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
synchronize_irq(rchan->irq);
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* IRQ handling * IRQ handling
*/ */
...@@ -1650,7 +1663,6 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, ...@@ -1650,7 +1663,6 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac,
struct dma_chan *chan = &rchan->chan; struct dma_chan *chan = &rchan->chan;
char pdev_irqname[5]; char pdev_irqname[5];
char *irqname; char *irqname;
int irq;
int ret; int ret;
rchan->index = index; rchan->index = index;
...@@ -1667,8 +1679,8 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, ...@@ -1667,8 +1679,8 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac,
/* Request the channel interrupt. */ /* Request the channel interrupt. */
sprintf(pdev_irqname, "ch%u", index); sprintf(pdev_irqname, "ch%u", index);
irq = platform_get_irq_byname(pdev, pdev_irqname); rchan->irq = platform_get_irq_byname(pdev, pdev_irqname);
if (irq < 0) { if (rchan->irq < 0) {
dev_err(dmac->dev, "no IRQ specified for channel %u\n", index); dev_err(dmac->dev, "no IRQ specified for channel %u\n", index);
return -ENODEV; return -ENODEV;
} }
...@@ -1678,11 +1690,13 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, ...@@ -1678,11 +1690,13 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac,
if (!irqname) if (!irqname)
return -ENOMEM; return -ENOMEM;
ret = devm_request_threaded_irq(dmac->dev, irq, rcar_dmac_isr_channel, ret = devm_request_threaded_irq(dmac->dev, rchan->irq,
rcar_dmac_isr_channel,
rcar_dmac_isr_channel_thread, 0, rcar_dmac_isr_channel_thread, 0,
irqname, rchan); irqname, rchan);
if (ret) { if (ret) {
dev_err(dmac->dev, "failed to request IRQ %u (%d)\n", irq, ret); dev_err(dmac->dev, "failed to request IRQ %u (%d)\n",
rchan->irq, ret);
return ret; return ret;
} }
...@@ -1846,6 +1860,7 @@ static int rcar_dmac_probe(struct platform_device *pdev) ...@@ -1846,6 +1860,7 @@ static int rcar_dmac_probe(struct platform_device *pdev)
engine->device_terminate_all = rcar_dmac_chan_terminate_all; engine->device_terminate_all = rcar_dmac_chan_terminate_all;
engine->device_tx_status = rcar_dmac_tx_status; engine->device_tx_status = rcar_dmac_tx_status;
engine->device_issue_pending = rcar_dmac_issue_pending; engine->device_issue_pending = rcar_dmac_issue_pending;
engine->device_synchronize = rcar_dmac_device_synchronize;
ret = dma_async_device_register(engine); ret = dma_async_device_register(engine);
if (ret < 0) if (ret < 0)
......
...@@ -2528,10 +2528,7 @@ dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, ...@@ -2528,10 +2528,7 @@ dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
dma_addr += period_len; dma_addr += period_len;
} }
sg[periods].offset = 0; sg_chain(sg, periods + 1, sg);
sg_dma_len(&sg[periods]) = 0;
sg[periods].page_link =
((unsigned long)sg | 0x01) & ~0x02;
txd = d40_prep_sg(chan, sg, sg, periods, direction, txd = d40_prep_sg(chan, sg, sg, periods, direction,
DMA_PREP_INTERRUPT); DMA_PREP_INTERRUPT);
......
...@@ -1492,37 +1492,9 @@ static int tegra_dma_remove(struct platform_device *pdev) ...@@ -1492,37 +1492,9 @@ static int tegra_dma_remove(struct platform_device *pdev)
} }
static int tegra_dma_runtime_suspend(struct device *dev) static int tegra_dma_runtime_suspend(struct device *dev)
{
struct tegra_dma *tdma = dev_get_drvdata(dev);
clk_disable_unprepare(tdma->dma_clk);
return 0;
}
static int tegra_dma_runtime_resume(struct device *dev)
{
struct tegra_dma *tdma = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(tdma->dma_clk);
if (ret < 0) {
dev_err(dev, "clk_enable failed: %d\n", ret);
return ret;
}
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int tegra_dma_pm_suspend(struct device *dev)
{ {
struct tegra_dma *tdma = dev_get_drvdata(dev); struct tegra_dma *tdma = dev_get_drvdata(dev);
int i; int i;
int ret;
/* Enable clock before accessing register */
ret = pm_runtime_get_sync(dev);
if (ret < 0)
return ret;
tdma->reg_gen = tdma_read(tdma, TEGRA_APBDMA_GENERAL); tdma->reg_gen = tdma_read(tdma, TEGRA_APBDMA_GENERAL);
for (i = 0; i < tdma->chip_data->nr_channels; i++) { for (i = 0; i < tdma->chip_data->nr_channels; i++) {
...@@ -1543,21 +1515,21 @@ static int tegra_dma_pm_suspend(struct device *dev) ...@@ -1543,21 +1515,21 @@ static int tegra_dma_pm_suspend(struct device *dev)
TEGRA_APBDMA_CHAN_WCOUNT); TEGRA_APBDMA_CHAN_WCOUNT);
} }
/* Disable clock */ clk_disable_unprepare(tdma->dma_clk);
pm_runtime_put(dev);
return 0; return 0;
} }
static int tegra_dma_pm_resume(struct device *dev) static int tegra_dma_runtime_resume(struct device *dev)
{ {
struct tegra_dma *tdma = dev_get_drvdata(dev); struct tegra_dma *tdma = dev_get_drvdata(dev);
int i; int i, ret;
int ret;
/* Enable clock before accessing register */ ret = clk_prepare_enable(tdma->dma_clk);
ret = pm_runtime_get_sync(dev); if (ret < 0) {
if (ret < 0) dev_err(dev, "clk_enable failed: %d\n", ret);
return ret; return ret;
}
tdma_write(tdma, TEGRA_APBDMA_GENERAL, tdma->reg_gen); tdma_write(tdma, TEGRA_APBDMA_GENERAL, tdma->reg_gen);
tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0); tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0);
...@@ -1582,16 +1554,14 @@ static int tegra_dma_pm_resume(struct device *dev) ...@@ -1582,16 +1554,14 @@ static int tegra_dma_pm_resume(struct device *dev)
(ch_reg->csr & ~TEGRA_APBDMA_CSR_ENB)); (ch_reg->csr & ~TEGRA_APBDMA_CSR_ENB));
} }
/* Disable clock */
pm_runtime_put(dev);
return 0; return 0;
} }
#endif
static const struct dev_pm_ops tegra_dma_dev_pm_ops = { static const struct dev_pm_ops tegra_dma_dev_pm_ops = {
SET_RUNTIME_PM_OPS(tegra_dma_runtime_suspend, tegra_dma_runtime_resume, SET_RUNTIME_PM_OPS(tegra_dma_runtime_suspend, tegra_dma_runtime_resume,
NULL) NULL)
SET_SYSTEM_SLEEP_PM_OPS(tegra_dma_pm_suspend, tegra_dma_pm_resume) SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
}; };
static const struct of_device_id tegra_dma_of_match[] = { static const struct of_device_id tegra_dma_of_match[] = {
......
...@@ -794,9 +794,6 @@ static struct dma_async_tx_descriptor *zynqmp_dma_prep_memcpy( ...@@ -794,9 +794,6 @@ static struct dma_async_tx_descriptor *zynqmp_dma_prep_memcpy(
chan = to_chan(dchan); chan = to_chan(dchan);
if (len > ZYNQMP_DMA_MAX_TRANS_LEN)
return NULL;
desc_cnt = DIV_ROUND_UP(len, ZYNQMP_DMA_MAX_TRANS_LEN); desc_cnt = DIV_ROUND_UP(len, ZYNQMP_DMA_MAX_TRANS_LEN);
spin_lock_bh(&chan->lock); spin_lock_bh(&chan->lock);
......
...@@ -44,7 +44,14 @@ ...@@ -44,7 +44,14 @@
#define PL080_SYNC (0x34) #define PL080_SYNC (0x34)
/* Per channel configuration registers */ /* The Faraday Technology FTDMAC020 variant registers */
#define FTDMAC020_CH_BUSY (0x20)
/* Identical to PL080_CONFIG */
#define FTDMAC020_CSR (0x24)
/* Identical to PL080_SYNC */
#define FTDMAC020_SYNC (0x2C)
#define FTDMAC020_REVISION (0x30)
#define FTDMAC020_FEATURE (0x34)
/* Per channel configuration registers */ /* Per channel configuration registers */
#define PL080_Cx_BASE(x) ((0x100 + (x * 0x20))) #define PL080_Cx_BASE(x) ((0x100 + (x * 0x20)))
...@@ -55,13 +62,20 @@ ...@@ -55,13 +62,20 @@
#define PL080_CH_CONFIG (0x10) #define PL080_CH_CONFIG (0x10)
#define PL080S_CH_CONTROL2 (0x10) #define PL080S_CH_CONTROL2 (0x10)
#define PL080S_CH_CONFIG (0x14) #define PL080S_CH_CONFIG (0x14)
/* The Faraday FTDMAC020 derivative shuffles the registers around */
#define PL080_LLI_ADDR_MASK (0x3fffffff << 2) #define FTDMAC020_CH_CSR (0x00)
#define FTDMAC020_CH_CFG (0x04)
#define FTDMAC020_CH_SRC_ADDR (0x08)
#define FTDMAC020_CH_DST_ADDR (0x0C)
#define FTDMAC020_CH_LLP (0x10)
#define FTDMAC020_CH_SIZE (0x14)
#define PL080_LLI_ADDR_MASK GENMASK(31, 2)
#define PL080_LLI_ADDR_SHIFT (2) #define PL080_LLI_ADDR_SHIFT (2)
#define PL080_LLI_LM_AHB2 BIT(0) #define PL080_LLI_LM_AHB2 BIT(0)
#define PL080_CONTROL_TC_IRQ_EN BIT(31) #define PL080_CONTROL_TC_IRQ_EN BIT(31)
#define PL080_CONTROL_PROT_MASK (0x7 << 28) #define PL080_CONTROL_PROT_MASK GENMASK(30, 28)
#define PL080_CONTROL_PROT_SHIFT (28) #define PL080_CONTROL_PROT_SHIFT (28)
#define PL080_CONTROL_PROT_CACHE BIT(30) #define PL080_CONTROL_PROT_CACHE BIT(30)
#define PL080_CONTROL_PROT_BUFF BIT(29) #define PL080_CONTROL_PROT_BUFF BIT(29)
...@@ -70,16 +84,16 @@ ...@@ -70,16 +84,16 @@
#define PL080_CONTROL_SRC_INCR BIT(26) #define PL080_CONTROL_SRC_INCR BIT(26)
#define PL080_CONTROL_DST_AHB2 BIT(25) #define PL080_CONTROL_DST_AHB2 BIT(25)
#define PL080_CONTROL_SRC_AHB2 BIT(24) #define PL080_CONTROL_SRC_AHB2 BIT(24)
#define PL080_CONTROL_DWIDTH_MASK (0x7 << 21) #define PL080_CONTROL_DWIDTH_MASK GENMASK(23, 21)
#define PL080_CONTROL_DWIDTH_SHIFT (21) #define PL080_CONTROL_DWIDTH_SHIFT (21)
#define PL080_CONTROL_SWIDTH_MASK (0x7 << 18) #define PL080_CONTROL_SWIDTH_MASK GENMASK(20, 18)
#define PL080_CONTROL_SWIDTH_SHIFT (18) #define PL080_CONTROL_SWIDTH_SHIFT (18)
#define PL080_CONTROL_DB_SIZE_MASK (0x7 << 15) #define PL080_CONTROL_DB_SIZE_MASK GENMASK(17, 15)
#define PL080_CONTROL_DB_SIZE_SHIFT (15) #define PL080_CONTROL_DB_SIZE_SHIFT (15)
#define PL080_CONTROL_SB_SIZE_MASK (0x7 << 12) #define PL080_CONTROL_SB_SIZE_MASK GENMASK(14, 12)
#define PL080_CONTROL_SB_SIZE_SHIFT (12) #define PL080_CONTROL_SB_SIZE_SHIFT (12)
#define PL080_CONTROL_TRANSFER_SIZE_MASK (0xfff << 0) #define PL080_CONTROL_TRANSFER_SIZE_MASK GENMASK(11, 0)
#define PL080S_CONTROL_TRANSFER_SIZE_MASK (0x1ffffff << 0) #define PL080S_CONTROL_TRANSFER_SIZE_MASK GENMASK(24, 0)
#define PL080_CONTROL_TRANSFER_SIZE_SHIFT (0) #define PL080_CONTROL_TRANSFER_SIZE_SHIFT (0)
#define PL080_BSIZE_1 (0x0) #define PL080_BSIZE_1 (0x0)
...@@ -102,11 +116,11 @@ ...@@ -102,11 +116,11 @@
#define PL080_CONFIG_LOCK BIT(16) #define PL080_CONFIG_LOCK BIT(16)
#define PL080_CONFIG_TC_IRQ_MASK BIT(15) #define PL080_CONFIG_TC_IRQ_MASK BIT(15)
#define PL080_CONFIG_ERR_IRQ_MASK BIT(14) #define PL080_CONFIG_ERR_IRQ_MASK BIT(14)
#define PL080_CONFIG_FLOW_CONTROL_MASK (0x7 << 11) #define PL080_CONFIG_FLOW_CONTROL_MASK GENMASK(13, 11)
#define PL080_CONFIG_FLOW_CONTROL_SHIFT (11) #define PL080_CONFIG_FLOW_CONTROL_SHIFT (11)
#define PL080_CONFIG_DST_SEL_MASK (0xf << 6) #define PL080_CONFIG_DST_SEL_MASK GENMASK(9, 6)
#define PL080_CONFIG_DST_SEL_SHIFT (6) #define PL080_CONFIG_DST_SEL_SHIFT (6)
#define PL080_CONFIG_SRC_SEL_MASK (0xf << 1) #define PL080_CONFIG_SRC_SEL_MASK GENMASK(4, 1)
#define PL080_CONFIG_SRC_SEL_SHIFT (1) #define PL080_CONFIG_SRC_SEL_SHIFT (1)
#define PL080_CONFIG_ENABLE BIT(0) #define PL080_CONFIG_ENABLE BIT(0)
...@@ -119,6 +133,73 @@ ...@@ -119,6 +133,73 @@
#define PL080_FLOW_PER2MEM_PER (0x6) #define PL080_FLOW_PER2MEM_PER (0x6)
#define PL080_FLOW_SRC2DST_SRC (0x7) #define PL080_FLOW_SRC2DST_SRC (0x7)
#define FTDMAC020_CH_CSR_TC_MSK BIT(31)
/* Later versions have a threshold in bits 24..26, */
#define FTDMAC020_CH_CSR_FIFOTH_MSK GENMASK(26, 24)
#define FTDMAC020_CH_CSR_FIFOTH_SHIFT (24)
#define FTDMAC020_CH_CSR_CHPR1_MSK GENMASK(23, 22)
#define FTDMAC020_CH_CSR_PROT3 BIT(21)
#define FTDMAC020_CH_CSR_PROT2 BIT(20)
#define FTDMAC020_CH_CSR_PROT1 BIT(19)
#define FTDMAC020_CH_CSR_SRC_SIZE_MSK GENMASK(18, 16)
#define FTDMAC020_CH_CSR_SRC_SIZE_SHIFT (16)
#define FTDMAC020_CH_CSR_ABT BIT(15)
#define FTDMAC020_CH_CSR_SRC_WIDTH_MSK GENMASK(13, 11)
#define FTDMAC020_CH_CSR_SRC_WIDTH_SHIFT (11)
#define FTDMAC020_CH_CSR_DST_WIDTH_MSK GENMASK(10, 8)
#define FTDMAC020_CH_CSR_DST_WIDTH_SHIFT (8)
#define FTDMAC020_CH_CSR_MODE BIT(7)
/* 00 = increase, 01 = decrease, 10 = fix */
#define FTDMAC020_CH_CSR_SRCAD_CTL_MSK GENMASK(6, 5)
#define FTDMAC020_CH_CSR_SRCAD_CTL_SHIFT (5)
#define FTDMAC020_CH_CSR_DSTAD_CTL_MSK GENMASK(4, 3)
#define FTDMAC020_CH_CSR_DSTAD_CTL_SHIFT (3)
#define FTDMAC020_CH_CSR_SRC_SEL BIT(2)
#define FTDMAC020_CH_CSR_DST_SEL BIT(1)
#define FTDMAC020_CH_CSR_EN BIT(0)
/* FIFO threshold setting */
#define FTDMAC020_CH_CSR_FIFOTH_1 (0x0)
#define FTDMAC020_CH_CSR_FIFOTH_2 (0x1)
#define FTDMAC020_CH_CSR_FIFOTH_4 (0x2)
#define FTDMAC020_CH_CSR_FIFOTH_8 (0x3)
#define FTDMAC020_CH_CSR_FIFOTH_16 (0x4)
/* The FTDMAC020 supports 64bit wide transfers */
#define FTDMAC020_WIDTH_64BIT (0x3)
/* Address can be increased, decreased or fixed */
#define FTDMAC020_CH_CSR_SRCAD_CTL_INC (0x0)
#define FTDMAC020_CH_CSR_SRCAD_CTL_DEC (0x1)
#define FTDMAC020_CH_CSR_SRCAD_CTL_FIXED (0x2)
#define FTDMAC020_CH_CFG_LLP_CNT_MASK GENMASK(19, 16)
#define FTDMAC020_CH_CFG_LLP_CNT_SHIFT (16)
#define FTDMAC020_CH_CFG_BUSY BIT(8)
#define FTDMAC020_CH_CFG_INT_ABT_MASK BIT(2)
#define FTDMAC020_CH_CFG_INT_ERR_MASK BIT(1)
#define FTDMAC020_CH_CFG_INT_TC_MASK BIT(0)
/* Inside the LLIs, the applicable CSR fields are mapped differently */
#define FTDMAC020_LLI_TC_MSK BIT(28)
#define FTDMAC020_LLI_SRC_WIDTH_MSK GENMASK(27, 25)
#define FTDMAC020_LLI_SRC_WIDTH_SHIFT (25)
#define FTDMAC020_LLI_DST_WIDTH_MSK GENMASK(24, 22)
#define FTDMAC020_LLI_DST_WIDTH_SHIFT (22)
#define FTDMAC020_LLI_SRCAD_CTL_MSK GENMASK(21, 20)
#define FTDMAC020_LLI_SRCAD_CTL_SHIFT (20)
#define FTDMAC020_LLI_DSTAD_CTL_MSK GENMASK(19, 18)
#define FTDMAC020_LLI_DSTAD_CTL_SHIFT (18)
#define FTDMAC020_LLI_SRC_SEL BIT(17)
#define FTDMAC020_LLI_DST_SEL BIT(16)
#define FTDMAC020_LLI_TRANSFER_SIZE_MASK GENMASK(11, 0)
#define FTDMAC020_LLI_TRANSFER_SIZE_SHIFT (0)
#define FTDMAC020_CFG_LLP_CNT_MASK GENMASK(19, 16)
#define FTDMAC020_CFG_LLP_CNT_SHIFT (16)
#define FTDMAC020_CFG_BUSY BIT(8)
#define FTDMAC020_CFG_INT_ABT_MSK BIT(2)
#define FTDMAC020_CFG_INT_ERR_MSK BIT(1)
#define FTDMAC020_CFG_INT_TC_MSK BIT(0)
/* DMA linked list chain structure */ /* DMA linked list chain structure */
struct pl080_lli { struct pl080_lli {
......
...@@ -47,8 +47,6 @@ enum { ...@@ -47,8 +47,6 @@ enum {
* devices with static assignments * devices with static assignments
* @muxval: a number usually used to poke into some mux regiser to * @muxval: a number usually used to poke into some mux regiser to
* mux in the signal to this channel * mux in the signal to this channel
* @cctl_memcpy: options for the channel control register for memcpy
* *** not used for slave channels ***
* @addr: source/target address in physical memory for this DMA channel, * @addr: source/target address in physical memory for this DMA channel,
* can be the address of a FIFO register for burst requests for example. * can be the address of a FIFO register for burst requests for example.
* This can be left undefined if the PrimeCell API is used for configuring * This can be left undefined if the PrimeCell API is used for configuring
...@@ -63,12 +61,28 @@ struct pl08x_channel_data { ...@@ -63,12 +61,28 @@ struct pl08x_channel_data {
int min_signal; int min_signal;
int max_signal; int max_signal;
u32 muxval; u32 muxval;
u32 cctl_memcpy;
dma_addr_t addr; dma_addr_t addr;
bool single; bool single;
u8 periph_buses; u8 periph_buses;
}; };
enum pl08x_burst_size {
PL08X_BURST_SZ_1,
PL08X_BURST_SZ_4,
PL08X_BURST_SZ_8,
PL08X_BURST_SZ_16,
PL08X_BURST_SZ_32,
PL08X_BURST_SZ_64,
PL08X_BURST_SZ_128,
PL08X_BURST_SZ_256,
};
enum pl08x_bus_width {
PL08X_BUS_WIDTH_8_BITS,
PL08X_BUS_WIDTH_16_BITS,
PL08X_BUS_WIDTH_32_BITS,
};
/** /**
* struct pl08x_platform_data - the platform configuration for the PL08x * struct pl08x_platform_data - the platform configuration for the PL08x
* PrimeCells. * PrimeCells.
...@@ -76,6 +90,11 @@ struct pl08x_channel_data { ...@@ -76,6 +90,11 @@ struct pl08x_channel_data {
* platform, all inclusive, including multiplexed channels. The available * platform, all inclusive, including multiplexed channels. The available
* physical channels will be multiplexed around these signals as they are * physical channels will be multiplexed around these signals as they are
* requested, just enumerate all possible channels. * requested, just enumerate all possible channels.
* @num_slave_channels: number of elements in the slave channel array
* @memcpy_burst_size: the appropriate burst size for memcpy operations
* @memcpy_bus_width: memory bus width
* @memcpy_prot_buff: whether memcpy DMA is bufferable
* @memcpy_prot_cache: whether memcpy DMA is cacheable
* @get_xfer_signal: request a physical signal to be used for a DMA transfer * @get_xfer_signal: request a physical signal to be used for a DMA transfer
* immediately: if there is some multiplexing or similar blocking the use * immediately: if there is some multiplexing or similar blocking the use
* of the channel the transfer can be denied by returning less than zero, * of the channel the transfer can be denied by returning less than zero,
...@@ -90,7 +109,10 @@ struct pl08x_channel_data { ...@@ -90,7 +109,10 @@ struct pl08x_channel_data {
struct pl08x_platform_data { struct pl08x_platform_data {
struct pl08x_channel_data *slave_channels; struct pl08x_channel_data *slave_channels;
unsigned int num_slave_channels; unsigned int num_slave_channels;
struct pl08x_channel_data memcpy_channel; enum pl08x_burst_size memcpy_burst_size;
enum pl08x_bus_width memcpy_bus_width;
bool memcpy_prot_buff;
bool memcpy_prot_cache;
int (*get_xfer_signal)(const struct pl08x_channel_data *); int (*get_xfer_signal)(const struct pl08x_channel_data *);
void (*put_xfer_signal)(const struct pl08x_channel_data *, int); void (*put_xfer_signal)(const struct pl08x_channel_data *, int);
u8 lli_buses; u8 lli_buses;
......
...@@ -142,6 +142,7 @@ int raid6_select_algo(void); ...@@ -142,6 +142,7 @@ int raid6_select_algo(void);
extern const u8 raid6_gfmul[256][256] __attribute__((aligned(256))); extern const u8 raid6_gfmul[256][256] __attribute__((aligned(256)));
extern const u8 raid6_vgfmul[256][32] __attribute__((aligned(256))); extern const u8 raid6_vgfmul[256][32] __attribute__((aligned(256)));
extern const u8 raid6_gfexp[256] __attribute__((aligned(256))); extern const u8 raid6_gfexp[256] __attribute__((aligned(256)));
extern const u8 raid6_gflog[256] __attribute__((aligned(256)));
extern const u8 raid6_gfinv[256] __attribute__((aligned(256))); extern const u8 raid6_gfinv[256] __attribute__((aligned(256)));
extern const u8 raid6_gfexi[256] __attribute__((aligned(256))); extern const u8 raid6_gfexi[256] __attribute__((aligned(256)));
......
...@@ -125,6 +125,26 @@ int main(int argc, char *argv[]) ...@@ -125,6 +125,26 @@ int main(int argc, char *argv[])
printf("EXPORT_SYMBOL(raid6_gfexp);\n"); printf("EXPORT_SYMBOL(raid6_gfexp);\n");
printf("#endif\n"); printf("#endif\n");
/* Compute log-of-2 table */
printf("\nconst u8 __attribute__((aligned(256)))\n"
"raid6_gflog[256] =\n" "{\n");
for (i = 0; i < 256; i += 8) {
printf("\t");
for (j = 0; j < 8; j++) {
v = 255;
for (k = 0; k < 256; k++)
if (exptbl[k] == (i + j)) {
v = k;
break;
}
printf("0x%02x,%c", v, (j == 7) ? '\n' : ' ');
}
}
printf("};\n");
printf("#ifdef __KERNEL__\n");
printf("EXPORT_SYMBOL(raid6_gflog);\n");
printf("#endif\n");
/* Compute inverse table x^-1 == x^254 */ /* Compute inverse table x^-1 == x^254 */
printf("\nconst u8 __attribute__((aligned(256)))\n" printf("\nconst u8 __attribute__((aligned(256)))\n"
"raid6_gfinv[256] =\n" "{\n"); "raid6_gfinv[256] =\n" "{\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment