diff options
31 files changed, 631 insertions, 397 deletions
diff --git a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt index 61315eaa7660..b1ba639554c0 100644 --- a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt +++ b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt @@ -29,6 +29,7 @@ Required Properties: - "renesas,dmac-r8a77965" (R-Car M3-N) - "renesas,dmac-r8a77970" (R-Car V3M) - "renesas,dmac-r8a77980" (R-Car V3H) + - "renesas,dmac-r8a77995" (R-Car D3) - reg: base address and length of the registers block for the DMAC diff --git a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt index 9dc935e24e55..482e54362d3e 100644 --- a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt +++ b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt @@ -12,6 +12,8 @@ Required Properties: - "renesas,r8a7795-usb-dmac" (R-Car H3) - "renesas,r8a7796-usb-dmac" (R-Car M3-W) - "renesas,r8a77965-usb-dmac" (R-Car M3-N) + - "renesas,r8a77990-usb-dmac" (R-Car E3) + - "renesas,r8a77995-usb-dmac" (R-Car D3) - reg: base address and length of the registers block for the DMAC - interrupts: interrupt specifiers for the DMAC, one for each entry in interrupt-names. diff --git a/MAINTAINERS b/MAINTAINERS index 3838c94a0d47..abec3381cf45 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11790,6 +11790,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/rkuo/linux-hexagon-kernel.g S: Supported F: arch/hexagon/ +QUALCOMM HIDMA DRIVER +M: Sinan Kaya <okaya@codeaurora.org> +L: linux-arm-kernel@lists.infradead.org +L: linux-arm-msm@vger.kernel.org +L: dmaengine@vger.kernel.org +S: Supported +F: drivers/dma/qcom/hidma* + QUALCOMM IOMMU M: Rob Clark <robdclark@gmail.com> L: iommu@lists.linux-foundation.org diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 6d61cd023633..ca1680afa20a 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -151,13 +151,6 @@ config DMA_JZ4780 If you have a board based on such a SoC and wish to use DMA for devices which can use the DMA controller, say Y or M here. -config DMA_OMAP - tristate "OMAP DMA support" - depends on ARCH_OMAP || COMPILE_TEST - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - select TI_DMA_CROSSBAR if (SOC_DRA7XX || COMPILE_TEST) - config DMA_SA11X0 tristate "SA-11x0 DMA support" depends on ARCH_SA1100 || COMPILE_TEST @@ -574,28 +567,6 @@ config TIMB_DMA help Enable support for the Timberdale FPGA DMA engine. -config TI_CPPI41 - tristate "CPPI 4.1 DMA support" - depends on (ARCH_OMAP || ARCH_DAVINCI_DA8XX) - select DMA_ENGINE - help - The Communications Port Programming Interface (CPPI) 4.1 DMA engine - is currently used by the USB driver on AM335x and DA8xx platforms. - -config TI_DMA_CROSSBAR - bool - -config TI_EDMA - bool "TI EDMA support" - depends on ARCH_DAVINCI || ARCH_OMAP || ARCH_KEYSTONE || COMPILE_TEST - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - select TI_DMA_CROSSBAR if (ARCH_OMAP || COMPILE_TEST) - default n - help - Enable support for the TI EDMA controller. This DMA - engine is found on TI DaVinci and AM33xx parts. - config XGENE_DMA tristate "APM X-Gene DMA support" depends on ARCH_XGENE || COMPILE_TEST @@ -653,6 +624,8 @@ source "drivers/dma/hsu/Kconfig" source "drivers/dma/sh/Kconfig" +source "drivers/dma/ti/Kconfig" + # clients comment "DMA Clients" depends on DMA_ENGINE diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 0f62a4d49aab..203a99d68315 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -24,7 +24,6 @@ obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o obj-$(CONFIG_DMA_BCM2835) += bcm2835-dma.o obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o obj-$(CONFIG_DMA_JZ4780) += dma-jz4780.o -obj-$(CONFIG_DMA_OMAP) += omap-dma.o obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o obj-$(CONFIG_DMA_SUN4I) += sun4i-dma.o obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o @@ -69,13 +68,11 @@ obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o obj-$(CONFIG_TEGRA210_ADMA) += tegra210-adma.o obj-$(CONFIG_TIMB_DMA) += timb_dma.o -obj-$(CONFIG_TI_CPPI41) += cppi41.o -obj-$(CONFIG_TI_DMA_CROSSBAR) += ti-dma-crossbar.o -obj-$(CONFIG_TI_EDMA) += edma.o obj-$(CONFIG_XGENE_DMA) += xgene-dma.o obj-$(CONFIG_ZX_DMA) += zx_dma.o obj-$(CONFIG_ST_FDMA) += st_fdma.o obj-y += mediatek/ obj-y += qcom/ +obj-y += ti/ obj-y += xilinx/ diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index a861b5b4d443..75f38d19fcbe 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -2041,8 +2041,7 @@ static void at_dma_shutdown(struct platform_device *pdev) static int at_dma_prepare(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct at_dma *atdma = platform_get_drvdata(pdev); + struct at_dma *atdma = dev_get_drvdata(dev); struct dma_chan *chan, *_chan; list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels, @@ -2076,8 +2075,7 @@ static void atc_suspend_cyclic(struct at_dma_chan *atchan) static int at_dma_suspend_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct at_dma *atdma = platform_get_drvdata(pdev); + struct at_dma *atdma = dev_get_drvdata(dev); struct dma_chan *chan, *_chan; /* preserve data */ @@ -2118,8 +2116,7 @@ static void atc_resume_cyclic(struct at_dma_chan *atchan) static int at_dma_resume_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct at_dma *atdma = platform_get_drvdata(pdev); + struct at_dma *atdma = dev_get_drvdata(dev); struct dma_chan *chan, *_chan; /* bring back DMA controller */ diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index 94236ec9d410..4bf72561667c 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -1833,8 +1833,7 @@ static void at_xdmac_free_chan_resources(struct dma_chan *chan) #ifdef CONFIG_PM static int atmel_xdmac_prepare(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct at_xdmac *atxdmac = platform_get_drvdata(pdev); + struct at_xdmac *atxdmac = dev_get_drvdata(dev); struct dma_chan *chan, *_chan; list_for_each_entry_safe(chan, _chan, &atxdmac->dma.channels, device_node) { @@ -1853,8 +1852,7 @@ static int atmel_xdmac_prepare(struct device *dev) #ifdef CONFIG_PM_SLEEP static int atmel_xdmac_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct at_xdmac *atxdmac = platform_get_drvdata(pdev); + struct at_xdmac *atxdmac = dev_get_drvdata(dev); struct dma_chan *chan, *_chan; list_for_each_entry_safe(chan, _chan, &atxdmac->dma.channels, device_node) { @@ -1878,8 +1876,7 @@ static int atmel_xdmac_suspend(struct device *dev) static int atmel_xdmac_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct at_xdmac *atxdmac = platform_get_drvdata(pdev); + struct at_xdmac *atxdmac = dev_get_drvdata(dev); struct at_xdmac_chan *atchan; struct dma_chan *chan, *_chan; int i; diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index 2419fe524daa..15b2453d2647 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -687,7 +687,7 @@ static int axi_dmac_probe(struct platform_device *pdev) if (ret) goto err_unregister_device; - ret = request_irq(dmac->irq, axi_dmac_interrupt_handler, 0, + ret = request_irq(dmac->irq, axi_dmac_interrupt_handler, IRQF_SHARED, dev_name(&pdev->dev), dmac); if (ret) goto err_unregister_of; diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index b9339524d5bd..aa1712beb0cc 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -468,6 +468,8 @@ static int dmatest_func(void *data) unsigned long long total_len = 0; u8 align = 0; bool is_memset = false; + dma_addr_t *srcs; + dma_addr_t *dma_pq; set_freezable(); @@ -551,6 +553,14 @@ static int dmatest_func(void *data) set_user_nice(current, 10); + srcs = kcalloc(src_cnt, sizeof(dma_addr_t), GFP_KERNEL); + if (!srcs) + goto err_dstbuf; + + dma_pq = kcalloc(dst_cnt, sizeof(dma_addr_t), GFP_KERNEL); + if (!dma_pq) + goto err_srcs_array; + /* * src and dst buffers are freed by ourselves below */ @@ -561,7 +571,6 @@ static int dmatest_func(void *data) && !(params->iterations && total_tests >= params->iterations)) { struct dma_async_tx_descriptor *tx = NULL; struct dmaengine_unmap_data *um; - dma_addr_t srcs[src_cnt]; dma_addr_t *dsts; unsigned int src_off, dst_off, len; @@ -676,8 +685,6 @@ static int dmatest_func(void *data) srcs, src_cnt, len, flags); else if (thread->type == DMA_PQ) { - dma_addr_t dma_pq[dst_cnt]; - for (i = 0; i < dst_cnt; i++) dma_pq[i] = dsts[i] + dst_off; tx = dev->device_prep_dma_pq(chan, dma_pq, srcs, @@ -779,6 +786,9 @@ static int dmatest_func(void *data) runtime = ktime_to_us(ktime); ret = 0; + kfree(dma_pq); +err_srcs_array: + kfree(srcs); err_dstbuf: for (i = 0; thread->udsts[i]; i++) kfree(thread->udsts[i]); diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index bc31fe802061..f62dd0944908 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -293,8 +293,7 @@ MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table); static int dw_suspend_late(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct dw_dma_chip *chip = platform_get_drvdata(pdev); + struct dw_dma_chip *chip = dev_get_drvdata(dev); dw_dma_disable(chip); clk_disable_unprepare(chip->clk); @@ -304,8 +303,7 @@ static int dw_suspend_late(struct device *dev) static int dw_resume_early(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct dw_dma_chip *chip = platform_get_drvdata(pdev); + struct dw_dma_chip *chip = dev_get_drvdata(dev); int ret; ret = clk_prepare_enable(chip->clk); diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 3eaece888e75..1117b5123a6f 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1328,8 +1328,7 @@ static int fsldma_of_remove(struct platform_device *op) #ifdef CONFIG_PM static int fsldma_suspend_late(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct fsldma_device *fdev = platform_get_drvdata(pdev); + struct fsldma_device *fdev = dev_get_drvdata(dev); struct fsldma_chan *chan; int i; @@ -1360,8 +1359,7 @@ out: static int fsldma_resume_early(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct fsldma_device *fdev = platform_get_drvdata(pdev); + struct fsldma_device *fdev = dev_get_drvdata(dev); struct fsldma_chan *chan; u32 mode; int i; diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c index 1953e57505f4..e5c911200bdb 100644 --- a/drivers/dma/idma64.c +++ b/drivers/dma/idma64.c @@ -670,8 +670,7 @@ static int idma64_platform_remove(struct platform_device *pdev) static int idma64_pm_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct idma64_chip *chip = platform_get_drvdata(pdev); + struct idma64_chip *chip = dev_get_drvdata(dev); idma64_off(chip->idma64); return 0; @@ -679,8 +678,7 @@ static int idma64_pm_suspend(struct device *dev) static int idma64_pm_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct idma64_chip *chip = platform_get_drvdata(pdev); + struct idma64_chip *chip = dev_get_drvdata(dev); idma64_on(chip->idma64); return 0; diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 715b39ae5a46..75b6ff0415ee 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -1,19 +1,13 @@ -/* - * drivers/dma/imx-dma.c - * - * This file contains a driver for the Freescale i.MX DMA engine - * found on i.MX1/21/27 - * - * Copyright 2010 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> - * Copyright 2012 Javier Martin, Vista Silicon <javier.martin@vista-silicon.com> - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// drivers/dma/imx-dma.c +// +// This file contains a driver for the Freescale i.MX DMA engine +// found on i.MX1/21/27 +// +// Copyright 2010 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> +// Copyright 2012 Javier Martin, Vista Silicon <javier.martin@vista-silicon.com> + #include <linux/err.h> #include <linux/init.h> #include <linux/types.h> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index ccd03c3cedfe..f077992635c2 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1,21 +1,14 @@ -/* - * drivers/dma/imx-sdma.c - * - * This file contains a driver for the Freescale Smart DMA engine - * - * Copyright 2010 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> - * - * Based on code from Freescale: - * - * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ +// SPDX-License-Identifier: GPL-2.0+ +// +// drivers/dma/imx-sdma.c +// +// This file contains a driver for the Freescale Smart DMA engine +// +// Copyright 2010 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> +// +// Based on code from Freescale: +// +// Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. #include <linux/init.h> #include <linux/iopoll.h> diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index 41d167921fab..ae5182ff0128 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -1,12 +1,8 @@ -/* - * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. - * - * Refer to drivers/dma/imx-sdma.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. +// +// Refer to drivers/dma/imx-sdma.c #include <linux/init.h> #include <linux/types.h> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index de1fd59fe136..6237069001c4 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -27,6 +27,7 @@ #include <linux/of_dma.h> #include <linux/err.h> #include <linux/pm_runtime.h> +#include <linux/bug.h> #include "dmaengine.h" #define PL330_MAX_CHAN 8 @@ -1094,51 +1095,96 @@ static inline int _ldst_memtomem(unsigned dry_run, u8 buf[], return off; } -static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run, - u8 buf[], const struct _xfer_spec *pxs, - int cyc) +static u32 _emit_load(unsigned int dry_run, u8 buf[], + enum pl330_cond cond, enum dma_transfer_direction direction, + u8 peri) { int off = 0; - enum pl330_cond cond; - if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) - cond = BURST; - else - cond = SINGLE; + switch (direction) { + case DMA_MEM_TO_MEM: + /* fall through */ + case DMA_MEM_TO_DEV: + off += _emit_LD(dry_run, &buf[off], cond); + break; - while (cyc--) { - off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); - off += _emit_LDP(dry_run, &buf[off], cond, pxs->desc->peri); - off += _emit_ST(dry_run, &buf[off], ALWAYS); + case DMA_DEV_TO_MEM: + if (cond == ALWAYS) { + off += _emit_LDP(dry_run, &buf[off], SINGLE, + peri); + off += _emit_LDP(dry_run, &buf[off], BURST, + peri); + } else { + off += _emit_LDP(dry_run, &buf[off], cond, + peri); + } + break; - if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) - off += _emit_FLUSHP(dry_run, &buf[off], - pxs->desc->peri); + default: + /* this code should be unreachable */ + WARN_ON(1); + break; } return off; } -static inline int _ldst_memtodev(struct pl330_dmac *pl330, +static inline u32 _emit_store(unsigned int dry_run, u8 buf[], + enum pl330_cond cond, enum dma_transfer_direction direction, + u8 peri) +{ + int off = 0; + + switch (direction) { + case DMA_MEM_TO_MEM: + /* fall through */ + case DMA_DEV_TO_MEM: + off += _emit_ST(dry_run, &buf[off], cond); + break; + + case DMA_MEM_TO_DEV: + if (cond == ALWAYS) { + off += _emit_STP(dry_run, &buf[off], SINGLE, + peri); + off += _emit_STP(dry_run, &buf[off], BURST, + peri); + } else { + off += _emit_STP(dry_run, &buf[off], cond, + peri); + } + break; + + default: + /* this code should be unreachable */ + WARN_ON(1); + break; + } + + return off; +} + +static inline int _ldst_peripheral(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], - const struct _xfer_spec *pxs, int cyc) + const struct _xfer_spec *pxs, int cyc, + enum pl330_cond cond) { int off = 0; - enum pl330_cond cond; if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) cond = BURST; - else - cond = SINGLE; + /* + * do FLUSHP at beginning to clear any stale dma requests before the + * first WFP. + */ + if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) + off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri); while (cyc--) { off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); - off += _emit_LD(dry_run, &buf[off], ALWAYS); - off += _emit_STP(dry_run, &buf[off], cond, pxs->desc->peri); - - if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) - off += _emit_FLUSHP(dry_run, &buf[off], - pxs->desc->peri); + off += _emit_load(dry_run, &buf[off], cond, pxs->desc->rqtype, + pxs->desc->peri); + off += _emit_store(dry_run, &buf[off], cond, pxs->desc->rqtype, + pxs->desc->peri); } return off; @@ -1148,19 +1194,65 @@ static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], const struct _xfer_spec *pxs, int cyc) { int off = 0; + enum pl330_cond cond = BRST_LEN(pxs->ccr) > 1 ? BURST : SINGLE; switch (pxs->desc->rqtype) { case DMA_MEM_TO_DEV: - off += _ldst_memtodev(pl330, dry_run, &buf[off], pxs, cyc); - break; + /* fall through */ case DMA_DEV_TO_MEM: - off += _ldst_devtomem(pl330, dry_run, &buf[off], pxs, cyc); + off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, cyc, + cond); break; + case DMA_MEM_TO_MEM: off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc); break; + + default: + /* this code should be unreachable */ + WARN_ON(1); + break; + } + + return off; +} + +/* + * transfer dregs with single transfers to peripheral, or a reduced size burst + * for mem-to-mem. + */ +static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[], + const struct _xfer_spec *pxs, int transfer_length) +{ + int off = 0; + int dregs_ccr; + + if (transfer_length == 0) + return off; + + switch (pxs->desc->rqtype) { + case DMA_MEM_TO_DEV: + /* fall through */ + case DMA_DEV_TO_MEM: + off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, + transfer_length, SINGLE); + break; + + case DMA_MEM_TO_MEM: + dregs_ccr = pxs->ccr; + dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) | + (0xf << CC_DSTBRSTLEN_SHFT)); + dregs_ccr |= (((transfer_length - 1) & 0xf) << + CC_SRCBRSTLEN_SHFT); + dregs_ccr |= (((transfer_length - 1) & 0xf) << + CC_DSTBRSTLEN_SHFT); + off += _emit_MOV(dry_run, &buf[off], CCR, dregs_ccr); + off += _ldst_memtomem(dry_run, &buf[off], pxs, 1); + break; + default: - off += 0x40000000; /* Scare off the Client */ + /* this code should be unreachable */ + WARN_ON(1); break; } @@ -1256,6 +1348,8 @@ static inline int _setup_loops(struct pl330_dmac *pl330, struct pl330_xfer *x = &pxs->desc->px; u32 ccr = pxs->ccr; unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr); + int num_dregs = (x->bytes - BURST_TO_BYTE(bursts, ccr)) / + BRST_SIZE(ccr); int off = 0; while (bursts) { @@ -1263,6 +1357,7 @@ static inline int _setup_loops(struct pl330_dmac *pl330, off += _loop(pl330, dry_run, &buf[off], &c, pxs); bursts -= c; } + off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs); return off; } @@ -1294,7 +1389,6 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run, struct _xfer_spec *pxs) { struct _pl330_req *req = &thrd->req[index]; - struct pl330_xfer *x; u8 *buf = req->mc_cpu; int off = 0; @@ -1303,11 +1397,6 @@ static int _setup_req(struct pl330_dmac *pl330, unsigned dry_run, /* DMAMOV CCR, ccr */ off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr); - x = &pxs->desc->px; - /* Error if xfer length is not aligned at burst size */ - if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) - return -EINVAL; - off += _setup_xfer(pl330, dry_run, &buf[off], pxs); /* DMASEV peripheral/event */ @@ -1365,6 +1454,20 @@ static int pl330_submit_req(struct pl330_thread *thrd, u32 ccr; int ret = 0; + switch (desc->rqtype) { + case DMA_MEM_TO_DEV: + break; + + case DMA_DEV_TO_MEM: + break; + + case DMA_MEM_TO_MEM: + break; + + default: + return -ENOTSUPP; + } + if (pl330->state == DYING || pl330->dmac_tbd.reset_chan & (1 << thrd->id)) { dev_info(thrd->dmac->ddma.dev, "%s:%d\n", @@ -2106,6 +2209,18 @@ static bool pl330_prep_slave_fifo(struct dma_pl330_chan *pch, return true; } +static int fixup_burst_len(int max_burst_len, int quirks) +{ + if (quirks & PL330_QUIRK_BROKEN_NO_FLUSHP) + return 1; + else if (max_burst_len > PL330_MAX_BURST) + return PL330_MAX_BURST; + else if (max_burst_len < 1) + return 1; + else + return max_burst_len; +} + static int pl330_config(struct dma_chan *chan, struct dma_slave_config *slave_config) { @@ -2117,15 +2232,15 @@ static int pl330_config(struct dma_chan *chan, pch->fifo_addr = slave_config->dst_addr; if (slave_config->dst_addr_width) pch->burst_sz = __ffs(slave_config->dst_addr_width); - if (slave_config->dst_maxburst) - pch->burst_len = slave_config->dst_maxburst; + pch->burst_len = fixup_burst_len(slave_config->dst_maxburst, + pch->dmac->quirks); } else if (slave_config->direction == DMA_DEV_TO_MEM) { if (slave_config->src_addr) pch->fifo_addr = slave_config->src_addr; if (slave_config->src_addr_width) pch->burst_sz = __ffs(slave_config->src_addr_width); - if (slave_config->src_maxburst) - pch->burst_len = slave_config->src_maxburst; + pch->burst_len = fixup_burst_len(slave_config->src_maxburst, + pch->dmac->quirks); } return 0; @@ -2519,14 +2634,8 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) burst_len >>= desc->rqcfg.brst_size; /* src/dst_burst_len can't be more than 16 */ - if (burst_len > 16) - burst_len = 16; - - while (burst_len > 1) { - if (!(len % (burst_len << desc->rqcfg.brst_size))) - break; - burst_len--; - } + if (burst_len > PL330_MAX_BURST) + burst_len = PL330_MAX_BURST; return burst_len; } @@ -2598,7 +2707,7 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( desc->rqtype = direction; desc->rqcfg.brst_size = pch->burst_sz; - desc->rqcfg.brst_len = 1; + desc->rqcfg.brst_len = pch->burst_len; desc->bytes_requested = period_len; fill_px(&desc->px, dst, src, period_len); @@ -2743,7 +2852,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, } desc->rqcfg.brst_size = pch->burst_sz; - desc->rqcfg.brst_len = 1; + desc->rqcfg.brst_len = pch->burst_len; desc->rqtype = direction; desc->bytes_requested = sg_dma_len(sg); } diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 4a828c18099a..1617715aa6e0 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -451,6 +451,7 @@ static void bam_reset_channel(struct bam_chan *bchan) /** * bam_chan_init_hw - Initialize channel hardware * @bchan: bam channel + * @dir: DMA transfer direction * * This function resets and initializes the BAM channel */ @@ -673,7 +674,7 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, remainder = 0; } - async_desc->length += desc->size; + async_desc->length += le16_to_cpu(desc->size); desc++; } while (remainder > 0); } @@ -687,7 +688,7 @@ err_out: /** * bam_dma_terminate_all - terminate all transactions on a channel - * @bchan: bam dma channel + * @chan: bam dma channel * * Dequeues and frees all transactions * No callbacks are done @@ -918,7 +919,8 @@ static enum dma_status bam_tx_status(struct dma_chan *chan, dma_cookie_t cookie, continue; for (i = 0; i < async_desc->num_desc; i++) - residue += async_desc->curr_desc[i].size; + residue += le16_to_cpu( + async_desc->curr_desc[i].size); } } @@ -958,7 +960,7 @@ static void bam_apply_new_config(struct bam_chan *bchan, /** * bam_start_dma - start next transaction - * @bchan - bam dma channel + * @bchan: bam dma channel */ static void bam_start_dma(struct bam_chan *bchan) { diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c index 963cc5228d05..43d4b00b8138 100644 --- a/drivers/dma/qcom/hidma.c +++ b/drivers/dma/qcom/hidma.c @@ -616,8 +616,7 @@ static irqreturn_t hidma_chirq_handler_msi(int chirq, void *arg) static ssize_t hidma_show_values(struct device *dev, struct device_attribute *attr, char *buf) { - struct platform_device *pdev = to_platform_device(dev); - struct hidma_dev *mdev = platform_get_drvdata(pdev); + struct hidma_dev *mdev = dev_get_drvdata(dev); buf[0] = 0; diff --git a/drivers/dma/qcom/hidma_mgmt_sys.c b/drivers/dma/qcom/hidma_mgmt_sys.c index d61f1068a34b..cbb89eafd844 100644 --- a/drivers/dma/qcom/hidma_mgmt_sys.c +++ b/drivers/dma/qcom/hidma_mgmt_sys.c @@ -107,8 +107,7 @@ static struct hidma_mgmt_fileinfo hidma_mgmt_files[] = { static ssize_t show_values(struct device *dev, struct device_attribute *attr, char *buf) { - struct platform_device *pdev = to_platform_device(dev); - struct hidma_mgmt_dev *mdev = platform_get_drvdata(pdev); + struct hidma_mgmt_dev *mdev = dev_get_drvdata(dev); unsigned int i; buf[0] = 0; @@ -125,8 +124 |