Commit 1b02dcb9 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull dmaengine updates from Vinod Koul:
 "This time we have couple of new drivers along with updates to drivers:

   - new drivers for the DesignWare AXI DMAC and MediaTek High-Speed DMA
     controllers

   - stm32 dma and qcom bam dma driver updates

   - norandom test option for dmatest"

* tag 'dmaengine-4.17-rc1' of git://git.infradead.org/users/vkoul/slave-dma: (30 commits)
  dmaengine: stm32-dma: properly mask irq bits
  dmaengine: stm32-dma: fix max items per transfer
  dmaengine: stm32-dma: fix DMA IRQ status handling
  dmaengine: stm32-dma: Improve memory burst management
  dmaengine: stm32-dma: fix typo and reported checkpatch warnings
  dmaengine: stm32-dma: fix incomplete configuration in cyclic mode
  dmaengine: stm32-dma: threshold manages with bitfield feature
  dt-bindings: stm32-dma: introduce DMA features bitfield
  dt-bindings: rcar-dmac: Document r8a77470 support
  dmaengine: rcar-dmac: Fix too early/late system suspend/resume callbacks
  dmaengine: dw-axi-dmac: fix spelling mistake: "catched" -> "caught"
  dmaengine: edma: Check the memory allocation for the memcpy dma device
  dmaengine: at_xdmac: fix rare residue corruption
  dmaengine: mediatek: update MAINTAINERS entry with MediaTek DMA driver
  dmaengine: mediatek: Add MediaTek High-Speed DMA controller for MT7622 and MT7623 SoC
  dt-bindings: dmaengine: Add MediaTek High-Speed DMA controller bindings
  dt-bindings: Document the Synopsys DW AXI DMA bindings
  dmaengine: Introduce DW AXI DMAC driver
  dmaengine: pl330: fix a race condition in case of threaded irqs
  dmaengine: imx-sdma: fix pagefault when channel is disabled during interrupt
  ...
parents 92589cbd 2ffb850e
MediaTek High-Speed DMA Controller
==================================
This device follows the generic DMA bindings defined in dma/dma.txt.
Required properties:
- compatible: Must be one of
"mediatek,mt7622-hsdma": for MT7622 SoC
"mediatek,mt7623-hsdma": for MT7623 SoC
- reg: Should contain the register's base address and length.
- interrupts: Should contain a reference to the interrupt used by this
device.
- clocks: Should be the clock specifiers corresponding to the entry in
clock-names property.
- clock-names: Should contain "hsdma" entries.
- power-domains: Phandle to the power domain that the device is part of
- #dma-cells: The length of the DMA specifier, must be <1>. This one cell
in dmas property of a client device represents the channel
number.
Example:
hsdma: dma-controller@1b007000 {
compatible = "mediatek,mt7623-hsdma";
reg = <0 0x1b007000 0 0x1000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_LOW>;
clocks = <&ethsys CLK_ETHSYS_HSDMA>;
clock-names = "hsdma";
power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>;
#dma-cells = <1>;
};
DMA clients must use the format described in dma/dma.txt file.
...@@ -15,6 +15,10 @@ Required properties: ...@@ -15,6 +15,10 @@ Required properties:
the secure world. the secure world.
- qcom,controlled-remotely : optional, indicates that the bam is controlled by - qcom,controlled-remotely : optional, indicates that the bam is controlled by
remote proccessor i.e. execution environment. remote proccessor i.e. execution environment.
- num-channels : optional, indicates supported number of DMA channels in a
remotely controlled bam.
- qcom,num-ees : optional, indicates supported number of Execution Environments
in a remotely controlled bam.
Example: Example:
......
...@@ -18,6 +18,7 @@ Required Properties: ...@@ -18,6 +18,7 @@ Required Properties:
Examples with soctypes are: Examples with soctypes are:
- "renesas,dmac-r8a7743" (RZ/G1M) - "renesas,dmac-r8a7743" (RZ/G1M)
- "renesas,dmac-r8a7745" (RZ/G1E) - "renesas,dmac-r8a7745" (RZ/G1E)
- "renesas,dmac-r8a77470" (RZ/G1C)
- "renesas,dmac-r8a7790" (R-Car H2) - "renesas,dmac-r8a7790" (R-Car H2)
- "renesas,dmac-r8a7791" (R-Car M2-W) - "renesas,dmac-r8a7791" (R-Car M2-W)
- "renesas,dmac-r8a7792" (R-Car V2H) - "renesas,dmac-r8a7792" (R-Car V2H)
...@@ -26,6 +27,7 @@ Required Properties: ...@@ -26,6 +27,7 @@ Required Properties:
- "renesas,dmac-r8a7795" (R-Car H3) - "renesas,dmac-r8a7795" (R-Car H3)
- "renesas,dmac-r8a7796" (R-Car M3-W) - "renesas,dmac-r8a7796" (R-Car M3-W)
- "renesas,dmac-r8a77970" (R-Car V3M) - "renesas,dmac-r8a77970" (R-Car V3M)
- "renesas,dmac-r8a77980" (R-Car V3H)
- reg: base address and length of the registers block for the DMAC - reg: base address and length of the registers block for the DMAC
......
...@@ -11,6 +11,7 @@ Required Properties: ...@@ -11,6 +11,7 @@ Required Properties:
- "renesas,r8a7794-usb-dmac" (R-Car E2) - "renesas,r8a7794-usb-dmac" (R-Car E2)
- "renesas,r8a7795-usb-dmac" (R-Car H3) - "renesas,r8a7795-usb-dmac" (R-Car H3)
- "renesas,r8a7796-usb-dmac" (R-Car M3-W) - "renesas,r8a7796-usb-dmac" (R-Car M3-W)
- "renesas,r8a77965-usb-dmac" (R-Car M3-N)
- reg: base address and length of the registers block for the DMAC - reg: base address and length of the registers block for the DMAC
- 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.
......
Synopsys DesignWare AXI DMA Controller
Required properties:
- compatible: "snps,axi-dma-1.01a"
- reg: Address range of the DMAC registers. This should include
all of the per-channel registers.
- interrupt: Should contain the DMAC interrupt number.
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device.
- dma-channels: Number of channels supported by hardware.
- snps,dma-masters: Number of AXI masters supported by the hardware.
- snps,data-width: Maximum AXI data width supported by hardware.
(0 - 8bits, 1 - 16bits, 2 - 32bits, ..., 6 - 512bits)
- snps,priority: Priority of channel. Array size is equal to the number of
dma-channels. Priority value must be programmed within [0:dma-channels-1]
range. (0 - minimum priority)
- snps,block-size: Maximum block size supported by the controller channel.
Array size is equal to the number of dma-channels.
Optional properties:
- snps,axi-max-burst-len: Restrict master AXI burst length by value specified
in this property. If this property is missing the maximum AXI burst length
supported by DMAC is used. [1:256]
Example:
dmac: dma-controller@80000 {
compatible = "snps,axi-dma-1.01a";
reg = <0x80000 0x400>;
clocks = <&core_clk>, <&cfgr_clk>;
clock-names = "core-clk", "cfgr-clk";
interrupt-parent = <&intc>;
interrupts = <27>;
dma-channels = <4>;
snps,dma-masters = <2>;
snps,data-width = <3>;
snps,block-size = <4096 4096 4096 4096>;
snps,priority = <0 1 2 3>;
snps,axi-max-burst-len = <16>;
};
...@@ -62,14 +62,14 @@ channel: a phandle to the DMA controller plus the following four integer cells: ...@@ -62,14 +62,14 @@ channel: a phandle to the DMA controller plus the following four integer cells:
0x1: medium 0x1: medium
0x2: high 0x2: high
0x3: very high 0x3: very high
4. A 32bit mask specifying the DMA FIFO threshold configuration which are device 4. A 32bit bitfield value specifying DMA features which are device dependent:
dependent: -bit 0-1: DMA FIFO threshold selection
-bit 0-1: Fifo threshold
0x0: 1/4 full FIFO 0x0: 1/4 full FIFO
0x1: 1/2 full FIFO 0x1: 1/2 full FIFO
0x2: 3/4 full FIFO 0x2: 3/4 full FIFO
0x3: full FIFO 0x3: full FIFO
Example: Example:
usart1: serial@40011000 { usart1: serial@40011000 {
......
...@@ -8859,6 +8859,15 @@ M: Sean Wang <sean.wang@mediatek.com> ...@@ -8859,6 +8859,15 @@ M: Sean Wang <sean.wang@mediatek.com>
S: Maintained S: Maintained
F: drivers/media/rc/mtk-cir.c F: drivers/media/rc/mtk-cir.c
MEDIATEK DMA DRIVER
M: Sean Wang <sean.wang@mediatek.com>
L: dmaengine@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/dma/mtk-*
F: drivers/dma/mediatek/
MEDIATEK PMIC LED DRIVER MEDIATEK PMIC LED DRIVER
M: Sean Wang <sean.wang@mediatek.com> M: Sean Wang <sean.wang@mediatek.com>
S: Maintained S: Maintained
...@@ -13482,6 +13491,12 @@ S: Maintained ...@@ -13482,6 +13491,12 @@ S: Maintained
F: drivers/gpio/gpio-dwapb.c F: drivers/gpio/gpio-dwapb.c
F: Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt F: Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
SYNOPSYS DESIGNWARE AXI DMAC DRIVER
M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
S: Maintained
F: drivers/dma/dwi-axi-dmac/
F: Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.txt
SYNOPSYS DESIGNWARE DMAC DRIVER SYNOPSYS DESIGNWARE DMAC DRIVER
M: Viresh Kumar <vireshk@kernel.org> M: Viresh Kumar <vireshk@kernel.org>
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com> R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
......
...@@ -187,6 +187,16 @@ config DMA_SUN6I ...@@ -187,6 +187,16 @@ config DMA_SUN6I
help help
Support for the DMA engine first found in Allwinner A31 SoCs. Support for the DMA engine first found in Allwinner A31 SoCs.
config DW_AXI_DMAC
tristate "Synopsys DesignWare AXI DMA support"
depends on OF || COMPILE_TEST
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
help
Enable support for Synopsys DesignWare AXI DMA controller.
NOTE: This driver wasn't tested on 64 bit platform because
of lack 64 bit platform with Synopsys DW AXI DMAC.
config EP93XX_DMA config EP93XX_DMA
bool "Cirrus Logic EP93xx DMA support" bool "Cirrus Logic EP93xx DMA support"
depends on ARCH_EP93XX || COMPILE_TEST depends on ARCH_EP93XX || COMPILE_TEST
...@@ -633,6 +643,8 @@ config ZX_DMA ...@@ -633,6 +643,8 @@ config ZX_DMA
# driver files # driver files
source "drivers/dma/bestcomm/Kconfig" source "drivers/dma/bestcomm/Kconfig"
source "drivers/dma/mediatek/Kconfig"
source "drivers/dma/qcom/Kconfig" source "drivers/dma/qcom/Kconfig"
source "drivers/dma/dw/Kconfig" source "drivers/dma/dw/Kconfig"
......
...@@ -28,6 +28,7 @@ obj-$(CONFIG_DMA_OMAP) += omap-dma.o ...@@ -28,6 +28,7 @@ obj-$(CONFIG_DMA_OMAP) += omap-dma.o
obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
obj-$(CONFIG_DMA_SUN4I) += sun4i-dma.o obj-$(CONFIG_DMA_SUN4I) += sun4i-dma.o
obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o
obj-$(CONFIG_DW_AXI_DMAC) += dw-axi-dmac/
obj-$(CONFIG_DW_DMAC_CORE) += dw/ obj-$(CONFIG_DW_DMAC_CORE) += dw/
obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
obj-$(CONFIG_FSL_DMA) += fsldma.o obj-$(CONFIG_FSL_DMA) += fsldma.o
...@@ -75,5 +76,6 @@ obj-$(CONFIG_XGENE_DMA) += xgene-dma.o ...@@ -75,5 +76,6 @@ obj-$(CONFIG_XGENE_DMA) += xgene-dma.o
obj-$(CONFIG_ZX_DMA) += zx_dma.o obj-$(CONFIG_ZX_DMA) += zx_dma.o
obj-$(CONFIG_ST_FDMA) += st_fdma.o obj-$(CONFIG_ST_FDMA) += st_fdma.o
obj-y += mediatek/
obj-y += qcom/ obj-y += qcom/
obj-y += xilinx/ obj-y += xilinx/
...@@ -1471,10 +1471,10 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, ...@@ -1471,10 +1471,10 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) { for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc; check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
rmb(); rmb();
initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
rmb();
cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC); cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
rmb(); rmb();
initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
rmb();
cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc; cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
rmb(); rmb();
......
...@@ -74,7 +74,11 @@ MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), " ...@@ -74,7 +74,11 @@ MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
static bool noverify; static bool noverify;
module_param(noverify, bool, S_IRUGO | S_IWUSR); module_param(noverify, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(noverify, "Disable random data setup and verification"); MODULE_PARM_DESC(noverify, "Disable data verification (default: verify)");
static bool norandom;
module_param(norandom, bool, 0644);
MODULE_PARM_DESC(norandom, "Disable random offset setup (default: random)");
static bool verbose; static bool verbose;
module_param(verbose, bool, S_IRUGO | S_IWUSR); module_param(verbose, bool, S_IRUGO | S_IWUSR);
...@@ -103,6 +107,7 @@ struct dmatest_params { ...@@ -103,6 +107,7 @@ struct dmatest_params {
unsigned int pq_sources; unsigned int pq_sources;
int timeout; int timeout;
bool noverify; bool noverify;
bool norandom;
}; };
/** /**
...@@ -575,7 +580,7 @@ static int dmatest_func(void *data) ...@@ -575,7 +580,7 @@ static int dmatest_func(void *data)
break; break;
} }
if (params->noverify) if (params->norandom)
len = params->buf_size; len = params->buf_size;
else else
len = dmatest_random() % params->buf_size + 1; len = dmatest_random() % params->buf_size + 1;
...@@ -586,17 +591,19 @@ static int dmatest_func(void *data) ...@@ -586,17 +591,19 @@ static int dmatest_func(void *data)
total_len += len; total_len += len;
if (params->noverify) { if (params->norandom) {
src_off = 0; src_off = 0;
dst_off = 0; dst_off = 0;
} else { } else {
start = ktime_get();
src_off = dmatest_random() % (params->buf_size - len + 1); src_off = dmatest_random() % (params->buf_size - len + 1);
dst_off = dmatest_random() % (params->buf_size - len + 1); dst_off = dmatest_random() % (params->buf_size - len + 1);
src_off = (src_off >> align) << align; src_off = (src_off >> align) << align;
dst_off = (dst_off >> align) << align; dst_off = (dst_off >> align) << align;
}
if (!params->noverify) {
start = ktime_get();
dmatest_init_srcs(thread->srcs, src_off, len, dmatest_init_srcs(thread->srcs, src_off, len,
params->buf_size, is_memset); params->buf_size, is_memset);
dmatest_init_dsts(thread->dsts, dst_off, len, dmatest_init_dsts(thread->dsts, dst_off, len,
...@@ -975,6 +982,7 @@ static void run_threaded_test(struct dmatest_info *info) ...@@ -975,6 +982,7 @@ static void run_threaded_test(struct dmatest_info *info)
params->pq_sources = pq_sources; params->pq_sources = pq_sources;
params->timeout = timeout; params->timeout = timeout;
params->noverify = noverify; params->noverify = noverify;
params->norandom = norandom;
request_channels(info, DMA_MEMCPY); request_channels(info, DMA_MEMCPY);
request_channels(info, DMA_MEMSET); request_channels(info, DMA_MEMSET);
......
obj-$(CONFIG_DW_AXI_DMAC) += dw-axi-dmac-platform.o
This diff is collapsed.
This diff is collapsed.
...@@ -1876,6 +1876,11 @@ static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode) ...@@ -1876,6 +1876,11 @@ static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode)
if (memcpy_channels) { if (memcpy_channels) {
m_ddev = devm_kzalloc(ecc->dev, sizeof(*m_ddev), GFP_KERNEL); m_ddev = devm_kzalloc(ecc->dev, sizeof(*m_ddev), GFP_KERNEL);
if (!m_ddev) {
dev_warn(ecc->dev, "memcpy is disabled due to OoM\n");
memcpy_channels = NULL;
goto ch_setup;
}
ecc->dma_memcpy = m_ddev; ecc->dma_memcpy = m_ddev;
dma_cap_zero(m_ddev->cap_mask); dma_cap_zero(m_ddev->cap_mask);
...@@ -1903,6 +1908,7 @@ static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode) ...@@ -1903,6 +1908,7 @@ static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode)
dev_info(ecc->dev, "memcpy is disabled\n"); dev_info(ecc->dev, "memcpy is disabled\n");
} }
ch_setup:
for (i = 0; i < ecc->num_channels; i++) { for (i = 0; i < ecc->num_channels; i++) {
struct edma_chan *echan = &ecc->slave_chans[i]; struct edma_chan *echan = &ecc->slave_chans[i];
echan->ch_num = EDMA_CTLR_CHAN(ecc->id, i); echan->ch_num = EDMA_CTLR_CHAN(ecc->id, i);
......
...@@ -338,6 +338,7 @@ struct sdma_channel { ...@@ -338,6 +338,7 @@ struct sdma_channel {
unsigned int chn_real_count; unsigned int chn_real_count;
struct tasklet_struct tasklet; struct tasklet_struct tasklet;
struct imx_dma_data data; struct imx_dma_data data;
bool enabled;
}; };
#define IMX_DMA_SG_LOOP BIT(0) #define IMX_DMA_SG_LOOP BIT(0)
...@@ -596,7 +597,14 @@ static int sdma_config_ownership(struct sdma_channel *sdmac, ...@@ -596,7 +597,14 @@ static int sdma_config_ownership(struct sdma_channel *sdmac,
static void sdma_enable_channel(struct sdma_engine *sdma, int channel) static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
{ {
unsigned long flags;
struct sdma_channel *sdmac = &sdma->channel[channel];
writel(BIT(channel), sdma->regs + SDMA_H_START); writel(BIT(channel), sdma->regs + SDMA_H_START);
spin_lock_irqsave(&sdmac->lock, flags);
sdmac->enabled = true;
spin_unlock_irqrestore(&sdmac->lock, flags);
} }
/* /*
...@@ -685,6 +693,14 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac) ...@@ -685,6 +693,14 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
struct sdma_buffer_descriptor *bd; struct sdma_buffer_descriptor *bd;
int error = 0; int error = 0;
enum dma_status old_status = sdmac->status; enum dma_status old_status = sdmac->status;
unsigned long flags;
spin_lock_irqsave(&sdmac->lock, flags);
if (!sdmac->enabled) {
spin_unlock_irqrestore(&sdmac->lock, flags);
return;
}
spin_unlock_irqrestore(&sdmac->lock, flags);
/* /*
* loop mode. Iterate over descriptors, re-setup them and * loop mode. Iterate over descriptors, re-setup them and
...@@ -938,10 +954,15 @@ static int sdma_disable_channel(struct dma_chan *chan) ...@@ -938,10 +954,15 @@ static int sdma_disable_channel(struct dma_chan *chan)
struct sdma_channel *sdmac = to_sdma_chan(chan); struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma; struct sdma_engine *sdma = sdmac->sdma;
int channel = sdmac->channel; int channel = sdmac->channel;
unsigned long flags;
writel_relaxed(BIT(channel), sdma->regs + SDMA_H_STATSTOP); writel_relaxed(BIT(channel), sdma->regs + SDMA_H_STATSTOP);
sdmac->status = DMA_ERROR; sdmac->status = DMA_ERROR;
spin_lock_irqsave(&sdmac->lock, flags);
sdmac->enabled = false;
spin_unlock_irqrestore(&sdmac->lock, flags);
return 0; return 0;
} }
......
config MTK_HSDMA
tristate "MediaTek High-Speed DMA controller support"
depends on ARCH_MEDIATEK || COMPILE_TEST
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
---help---
Enable support for High-Speed DMA controller on MediaTek
SoCs.
This controller provides the channels which is dedicated to
memory-to-memory transfer to offload from CPU through ring-
based descriptor management.
obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o
This diff is collapsed.
...@@ -1510,7 +1510,7 @@ static void pl330_dotask(unsigned long data) ...@@ -1510,7 +1510,7 @@ static void pl330_dotask(unsigned long data)
/* Returns 1 if state was updated, 0 otherwise */ /* Returns 1 if state was updated, 0 otherwise */
static int pl330_update(struct pl330_dmac *pl330) static int pl330_update(struct pl330_dmac *pl330)
{ {
struct dma_pl330_desc *descdone, *tmp; struct dma_pl330_desc *descdone;
unsigned long flags; unsigned long flags;
void __iomem *regs; void __iomem *regs;
u32 val; u32 val;
...@@ -1588,7 +1588,9 @@ static int pl330_update(struct pl330_dmac *pl330) ...@@ -1588,7 +1588,9 @@ static int pl330_update(struct pl330_dmac *pl330)
} }
/* Now that we are in no hurry, do the callbacks */ /* Now that we are in no hurry, do the callbacks */
list_for_each_entry_safe(descdone, tmp, &pl330->req_done, rqd) { while (!list_empty(&pl330->req_done)) {
descdone = list_first_entry(&pl330->req_done,
struct dma_pl330_desc, rqd);
list_del(&descdone->rqd); list_del(&descdone->rqd);
spin_unlock_irqrestore(&pl330->lock, flags); spin_unlock_irqrestore(&pl330->lock, flags);
dma_pl330_rqcb(descdone, PL330_ERR_NONE); dma_pl330_rqcb(descdone, PL330_ERR_NONE);
......
...@@ -393,6 +393,7 @@ struct bam_device { ...@@ -393,6 +393,7 @@ struct bam_device {
struct device_dma_parameters dma_parms; struct device_dma_parameters dma_parms;
struct bam_chan *channels; struct bam_chan *channels;
u32 num_channels; u32 num_channels;
u32 num_ees;
/* execution environment ID, from DT */ /* execution environment ID, from DT */
u32 ee; u32 ee;
...@@ -934,12 +935,15 @@ static void bam_apply_new_config(struct bam_chan *bchan, ...@@ -934,12 +935,15 @@ static void bam_apply_new_config(struct bam_chan *bchan,
struct bam_device *bdev = bchan->bdev; struct bam_device *bdev = bchan->bdev;
u32 maxburst; u32 maxburst;
if (!bdev->controlled_remotely) {
if (dir == DMA_DEV_TO_MEM) if (dir == DMA_DEV_TO_MEM)
maxburst = bchan->slave.src_maxburst; maxburst = bchan->slave.src_maxburst;
else else
maxburst = bchan->slave.dst_maxburst; maxburst = bchan->slave.dst_maxburst;
writel_relaxed(maxburst, bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD)); writel_relaxed(maxburst,
bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD));
}
bchan->reconfigure = 0; bchan->reconfigure = 0;
} }
...@@ -1128,15 +1132,19 @@ static int bam_init(struct bam_device *bdev) ...@@ -1128,15 +1132,19 @@ static int bam_init(struct bam_device *bdev)
u32 val; u32 val;
/* read revision and configuration information */ /* read revision and configuration information */
val = readl_relaxed(bam_addr(bdev, 0, BAM_REVISION)) >> NUM_EES_SHIFT; if (!bdev->num_ees) {
val &= NUM_EES_MASK; val = readl_relaxed(bam_addr(bdev, 0, BAM_REVISION));
bdev->num_ees = (val >> NUM_EES_SHIFT) & NUM_EES_MASK;
}
/* check that configured EE is within range */ /* check that configured EE is within range */
if (bdev->ee >= val) if (bdev->ee >= bdev->num_ees)
return -EINVAL; return -EINVAL;
if (!bdev->num_channels) {
val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES)); val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES));
bdev->num_channels = val & BAM_NUM_PIPES_MASK; bdev->num_channels = val & BAM_NUM_PIPES_MASK;
}
if (bdev->controlled_remotely) if (bdev->controlled_remotely)
return 0; return 0;
...@@ -1232,10 +1240,26 @@ static int bam_dma_probe(struct platform_device *pdev) ...@@ -1232,10 +1240,26 @@ static int bam_dma_probe(struct platform_device *pdev)
bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node, bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node,
"qcom,controlled-remotely"); "qcom,controlled-remotely");
if (bdev->controlled_remotely) {
ret = of_property_read_u32(pdev->dev.of_node, "num-channels",
&bdev->num_channels);
if (ret)
dev_err(bdev->dev, "num-channels unspecified in dt\n");
ret = of_property_read_u32(pdev->dev.of_node, "qcom,num-ees",
&bdev->num_ees);
if (ret)
dev_err(bdev->dev, "num-ees unspecified in dt\n");
}
bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk"); bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk");
if (IS_ERR(bdev->bamclk)) if (IS_ERR(bdev->bamclk)) {
if (!bdev->controlled_remotely)
return PTR_ERR(bdev->bamclk); return PTR_ERR(bdev->bamclk);
bdev->bamclk = NULL;
}
ret = clk_prepare_enable(bdev->bamclk); ret = clk_prepare_enable(bdev->bamclk);
if (ret) { if (ret) {
dev_err(bdev->dev, "failed to prepare/enable clock\n"); dev_err(bdev->dev, "failed to prepare/enable clock\n");
...@@ -1309,6 +1333,11 @@ static int bam_dma_probe(struct platform_device *pdev) ...@@ -1309,6 +1333,11 @@ static int bam_dma_probe(struct platform_device *pdev)
if (ret) if (ret)
goto err_unregister_dma; goto err_unregister_dma;
if (bdev->controlled_remotely) {
pm_runtime_disable(&pdev->dev);
return 0;
}
pm_runtime_irq_safe(&pdev->dev); pm_runtime_irq_safe(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, BAM_DMA_AUTOSUSPEND_DELAY); pm_runtime_set_autosuspend_delay(&pdev->dev, BAM_DMA_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev);
...@@ -1392,6 +1421,7 @@ static int __maybe_unused bam_dma_suspend(struct device *dev) ...@@ -1392,6 +1421,7 @@ static int __maybe_unused bam_dma_suspend(struct device *dev)
{ {
struct bam_device *bdev = dev_get_drvdata(dev); struct bam_device *bdev = dev_get_drvdata(dev);
if (!bdev->controlled_remotely)
pm_runtime_force_suspend(dev); pm_runtime_force_suspend(dev);
clk_unprepare(bdev->bamclk); clk_unprepare(bdev->bamclk);
...@@ -1408,6 +1438,7 @@ static int __maybe_unused bam_dma_resume(struct device *dev) ...@@ -1408,6 +1438,7 @@ static int __maybe_unused bam_dma_resume(struct device *dev)
if (ret) if (ret)
return ret; return ret;
if (!bdev->controlled_remotely)
pm_runtime_force_resume(dev); pm_runtime_force_resume(dev);
return 0; return 0;
......
...@@ -1301,8 +1301,17 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan, ...@@ -1301,8 +1301,17 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
* If the cookie doesn't correspond to the currently running transfer * If the cookie doesn't correspond to the currently running transfer
* then the descriptor hasn't been processed yet, and the residue is * then the descriptor hasn't been processed yet, and the residue is
* equal to the full descriptor size. * equal to the full descriptor size.
* Also, a client driver is possible to call this function before
* rcar_dmac_isr_channel_thread() runs. In this case, the "desc.running"
* will be the next descriptor, and the done list will appear. So, if
* the argument cookie matches the done list's cookie, we can assume
* the residue is zero.
*/ */
if (cookie != desc->async_tx.cookie) { if (cookie != desc->async_tx.cookie) {
list_for_each_entry(desc, &chan->desc.done, node) {
if (cookie == desc->async_tx.cookie)
return 0;
}
list_for_each_entry(desc, &chan->desc.pending, node) { list_for_each_entry(desc, &chan->desc.pending, node) {
if (cookie == desc->async_tx.cookie) if (cookie == desc->async_tx.cookie)
return desc->size; return desc->size;
...@@ -1677,7 +1686,7 @@ static const struct dev_pm_ops rcar_dmac_pm = { ...@@ -1677,7 +1686,7 @@ static const struct dev_pm_ops rcar_dmac_pm = {
* - Wait for the current transfer to complete and stop the device, * - Wait for the current transfer to complete and stop the device,
* - Resume transfers, if any. * - Resume transfers, if any.
*/ */
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume) pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(rcar_dmac_runtime_suspend, rcar_dmac_runtime_resume, SET_RUNTIME_PM_OPS(rcar_dmac_runtime_suspend, rcar_dmac_runtime_resume,
NULL) NULL)
......
This diff is collapsed.
...@@ -470,7 +470,11 @@ typedef void (*dma_async_tx_callback_result)(void *dma_async_param, ...@@ -470,7 +470,11 @@ typedef void (*dma_async_tx_callback_result)(void *dma_async_param,
const struct dmaengine_result *result); const struct dmaengine_result *result);
struct dmaengine_unmap_data { struct dmaengine_unmap_data {
#if IS_ENABLED(CONFIG_DMA_ENGINE_RAID)
u16 map_cnt;
#else
u8 map_cnt; u8 map_cnt;
#endif
u8 to_cnt; u8 to_cnt;
u8 from_cnt; u8 from_cnt;
u8 bidi_cnt; u8 bidi_cnt;
......
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