From baf32519979f22e34db255117449fd91a4ad3c53 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Tue, 31 May 2022 15:50:14 +0200 Subject: dt-bindings: dma: mediatek,uart-dma: add MT8365 bindings Add binding documentation in order to support the MT8365 SoC. Signed-off-by: Fabien Parent Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220531135026.238475-6-fparent@baylibre.com Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml b/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml index 54d68fc688b5..19ea8dcbcbce 100644 --- a/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml +++ b/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml @@ -22,6 +22,7 @@ properties: - items: - enum: - mediatek,mt2712-uart-dma + - mediatek,mt8365-uart-dma - mediatek,mt8516-uart-dma - const: mediatek,mt6577-uart-dma - enum: -- cgit v1.2.3 From 5f89b97e1fd5f5e6f1df78aade50d92ca7809b4b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 8 Jun 2022 17:42:01 +0200 Subject: dmaengine: dmatest: Remove spaces before tabs Scripts/checkpath.pl says "please, no space before tabs". Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/d863916120d043e3f9dd2f2670238c34f68f7d5f.1654702886.git.geert+renesas@glider.be Signed-off-by: Vinod Koul --- drivers/dma/dmatest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 0a2168a4ccb0..8ad8e7011d0b 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -579,10 +579,10 @@ static int dmatest_func(void *data) unsigned int total_tests = 0; dma_cookie_t cookie; enum dma_status status; - enum dma_ctrl_flags flags; + enum dma_ctrl_flags flags; u8 *pq_coefs = NULL; int ret; - unsigned int buf_size; + unsigned int buf_size; struct dmatest_data *src; struct dmatest_data *dst; int i; -- cgit v1.2.3 From e8ecf73adbb41ee00d5fbaf35c3edab252b5d30f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 8 Jun 2022 17:42:58 +0200 Subject: dmaengine: dmatest: Replace symbolic permissions by octal permissions Octal permissions are easier to read. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/a745b883288f95e999b71fac677bbc2daa13c22d.1654702928.git.geert+renesas@glider.be Signed-off-by: Vinod Koul --- drivers/dma/dmatest.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 8ad8e7011d0b..3253d1da2b3a 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -22,51 +22,50 @@ #include static unsigned int test_buf_size = 16384; -module_param(test_buf_size, uint, S_IRUGO | S_IWUSR); +module_param(test_buf_size, uint, 0644); MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); static char test_device[32]; -module_param_string(device, test_device, sizeof(test_device), - S_IRUGO | S_IWUSR); +module_param_string(device, test_device, sizeof(test_device), 0644); MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); static unsigned int threads_per_chan = 1; -module_param(threads_per_chan, uint, S_IRUGO | S_IWUSR); +module_param(threads_per_chan, uint, 0644); MODULE_PARM_DESC(threads_per_chan, "Number of threads to start per channel (default: 1)"); static unsigned int max_channels; -module_param(max_channels, uint, S_IRUGO | S_IWUSR); +module_param(max_channels, uint, 0644); MODULE_PARM_DESC(max_channels, "Maximum number of channels to use (default: all)"); static unsigned int iterations; -module_param(iterations, uint, S_IRUGO | S_IWUSR); +module_param(iterations, uint, 0644); MODULE_PARM_DESC(iterations, "Iterations before stopping test (default: infinite)"); static unsigned int dmatest; -module_param(dmatest, uint, S_IRUGO | S_IWUSR); +module_param(dmatest, uint, 0644); MODULE_PARM_DESC(dmatest, "dmatest 0-memcpy 1-memset (default: 0)"); static unsigned int xor_sources = 3; -module_param(xor_sources, uint, S_IRUGO | S_IWUSR); +module_param(xor_sources, uint, 0644); MODULE_PARM_DESC(xor_sources, "Number of xor source buffers (default: 3)"); static unsigned int pq_sources = 3; -module_param(pq_sources, uint, S_IRUGO | S_IWUSR); +module_param(pq_sources, uint, 0644); MODULE_PARM_DESC(pq_sources, "Number of p+q source buffers (default: 3)"); static int timeout = 3000; -module_param(timeout, int, S_IRUGO | S_IWUSR); +module_param(timeout, int, 0644); MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), " "Pass -1 for infinite timeout"); static bool noverify; -module_param(noverify, bool, S_IRUGO | S_IWUSR); +module_param(noverify, bool, 0644); MODULE_PARM_DESC(noverify, "Disable data verification (default: verify)"); static bool norandom; @@ -74,7 +73,7 @@ module_param(norandom, bool, 0644); MODULE_PARM_DESC(norandom, "Disable random offset setup (default: random)"); static bool verbose; -module_param(verbose, bool, S_IRUGO | S_IWUSR); +module_param(verbose, bool, 0644); MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)"); static int alignment = -1; @@ -86,7 +85,7 @@ module_param(transfer_size, uint, 0644); MODULE_PARM_DESC(transfer_size, "Optional custom transfer size in bytes (default: not used (0))"); static bool polled; -module_param(polled, bool, S_IRUGO | S_IWUSR); +module_param(polled, bool, 0644); MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts"); /** @@ -154,7 +153,7 @@ static const struct kernel_param_ops run_ops = { .get = dmatest_run_get, }; static bool dmatest_run; -module_param_cb(run, &run_ops, &dmatest_run, S_IRUGO | S_IWUSR); +module_param_cb(run, &run_ops, &dmatest_run, 0644); MODULE_PARM_DESC(run, "Run the test (default: false)"); static int dmatest_chan_set(const char *val, const struct kernel_param *kp); @@ -290,7 +289,7 @@ static const struct kernel_param_ops wait_ops = { .get = dmatest_wait_get, .set = param_set_bool, }; -module_param_cb(wait, &wait_ops, &wait, S_IRUGO); +module_param_cb(wait, &wait_ops, &wait, 0444); MODULE_PARM_DESC(wait, "Wait for tests to complete (default: false)"); static bool dmatest_match_channel(struct dmatest_params *params, -- cgit v1.2.3 From 23fbc87c8ae6f550a2c919370d44fd29cbb568aa Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 27 May 2022 23:55:08 +0200 Subject: dt-bindings: dma: Rewrite ST-Ericsson DMA40 to YAML This rewrites the ST-Ericsson DMA40 bindings in YAML. Cc: Lee Jones Cc: devicetree@vger.kernel.org Signed-off-by: Linus Walleij Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20220527215508.622374-1-linus.walleij@linaro.org Signed-off-by: Vinod Koul --- .../devicetree/bindings/dma/ste-dma40.txt | 138 ------------------ .../devicetree/bindings/dma/stericsson,dma40.yaml | 159 +++++++++++++++++++++ 2 files changed, 159 insertions(+), 138 deletions(-) delete mode 100644 Documentation/devicetree/bindings/dma/ste-dma40.txt create mode 100644 Documentation/devicetree/bindings/dma/stericsson,dma40.yaml diff --git a/Documentation/devicetree/bindings/dma/ste-dma40.txt b/Documentation/devicetree/bindings/dma/ste-dma40.txt deleted file mode 100644 index 99ab5c4d331e..000000000000 --- a/Documentation/devicetree/bindings/dma/ste-dma40.txt +++ /dev/null @@ -1,138 +0,0 @@ -* DMA40 DMA Controller - -Required properties: -- compatible: "stericsson,dma40" -- reg: Address range of the DMAC registers -- reg-names: Names of the above areas to use during resource look-up -- interrupt: Should contain the DMAC interrupt number -- #dma-cells: must be <3> -- memcpy-channels: Channels to be used for memcpy - -Optional properties: -- dma-channels: Number of channels supported by hardware - if not present - the driver will attempt to obtain the information from H/W -- disabled-channels: Channels which can not be used - -Example: - - dma: dma-controller@801c0000 { - compatible = "stericsson,db8500-dma40", "stericsson,dma40"; - reg = <0x801C0000 0x1000 0x40010000 0x800>; - reg-names = "base", "lcpa"; - interrupt-parent = <&intc>; - interrupts = <0 25 0x4>; - - #dma-cells = <2>; - memcpy-channels = <56 57 58 59 60>; - disabled-channels = <12>; - dma-channels = <8>; - }; - -Clients -Required properties: -- dmas: Comma separated list of dma channel requests -- dma-names: Names of the aforementioned requested channels - -Each dmas request consists of 4 cells: - 1. A phandle pointing to the DMA controller - 2. Device signal number, the signal line for single and burst requests - connected from the device to the DMA40 engine - 3. The DMA request line number (only when 'use fixed channel' is set) - 4. A 32bit mask specifying; mode, direction and endianness - [NB: This list will grow] - 0x00000001: Mode: - Logical channel when unset - Physical channel when set - 0x00000002: Direction: - Memory to Device when unset - Device to Memory when set - 0x00000004: Endianness: - Little endian when unset - Big endian when set - 0x00000008: Use fixed channel: - Use automatic channel selection when unset - Use DMA request line number when set - 0x00000010: Set channel as high priority: - Normal priority when unset - High priority when set - -Existing signal numbers for the DB8500 ASIC. Unless specified, the signals are -bidirectional, i.e. the same for RX and TX operations: - -0: SPI controller 0 -1: SD/MMC controller 0 (unused) -2: SD/MMC controller 1 (unused) -3: SD/MMC controller 2 (unused) -4: I2C port 1 -5: I2C port 3 -6: I2C port 2 -7: I2C port 4 -8: Synchronous Serial Port SSP0 -9: Synchronous Serial Port SSP1 -10: Multi-Channel Display Engine MCDE RX -11: UART port 2 -12: UART port 1 -13: UART port 0 -14: Multirate Serial Port MSP2 -15: I2C port 0 -16: USB OTG in/out endpoints 7 & 15 -17: USB OTG in/out endpoints 6 & 14 -18: USB OTG in/out endpoints 5 & 13 -19: USB OTG in/out endpoints 4 & 12 -20: SLIMbus or HSI channel 0 -21: SLIMbus or HSI channel 1 -22: SLIMbus or HSI channel 2 -23: SLIMbus or HSI channel 3 -24: Multimedia DSP SXA0 -25: Multimedia DSP SXA1 -26: Multimedia DSP SXA2 -27: Multimedia DSP SXA3 -28: SD/MM controller 2 -29: SD/MM controller 0 -30: MSP port 1 on DB8500 v1, MSP port 3 on DB8500 v2 -31: MSP port 0 or SLIMbus channel 0 -32: SD/MM controller 1 -33: SPI controller 2 -34: i2c3 RX2 TX2 -35: SPI controller 1 -36: USB OTG in/out endpoints 3 & 11 -37: USB OTG in/out endpoints 2 & 10 -38: USB OTG in/out endpoints 1 & 9 -39: USB OTG in/out endpoints 8 -40: SPI controller 3 -41: SD/MM controller 3 -42: SD/MM controller 4 -43: SD/MM controller 5 -44: Multimedia DSP SXA4 -45: Multimedia DSP SXA5 -46: SLIMbus channel 8 or Multimedia DSP SXA6 -47: SLIMbus channel 9 or Multimedia DSP SXA7 -48: Crypto Accelerator 1 -49: Crypto Accelerator 1 TX or Hash Accelerator 1 TX -50: Hash Accelerator 1 TX -51: memcpy TX (to be used by the DMA driver for memcpy operations) -52: SLIMbus or HSI channel 4 -53: SLIMbus or HSI channel 5 -54: SLIMbus or HSI channel 6 -55: SLIMbus or HSI channel 7 -56: memcpy (to be used by the DMA driver for memcpy operations) -57: memcpy (to be used by the DMA driver for memcpy operations) -58: memcpy (to be used by the DMA driver for memcpy operations) -59: memcpy (to be used by the DMA driver for memcpy operations) -60: memcpy (to be used by the DMA driver for memcpy operations) -61: Crypto Accelerator 0 -62: Crypto Accelerator 0 TX or Hash Accelerator 0 TX -63: Hash Accelerator 0 TX - -Example: - - uart@80120000 { - compatible = "arm,pl011", "arm,primecell"; - reg = <0x80120000 0x1000>; - interrupts = <0 11 0x4>; - - dmas = <&dma 13 0 0x2>, /* Logical - DevToMem */ - <&dma 13 0 0x0>; /* Logical - MemToDev */ - dma-names = "rx", "rx"; - - }; diff --git a/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml b/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml new file mode 100644 index 000000000000..8bddfb3b6fa0 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml @@ -0,0 +1,159 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/stericsson,dma40.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ST-Ericsson DMA40 DMA Engine + +maintainers: + - Linus Walleij + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + "#dma-cells": + const: 3 + description: | + The first cell is the unique device channel number as indicated by this + table for DB8500 which is the only ASIC known to use DMA40: + + 0: SPI controller 0 + 1: SD/MMC controller 0 (unused) + 2: SD/MMC controller 1 (unused) + 3: SD/MMC controller 2 (unused) + 4: I2C port 1 + 5: I2C port 3 + 6: I2C port 2 + 7: I2C port 4 + 8: Synchronous Serial Port SSP0 + 9: Synchronous Serial Port SSP1 + 10: Multi-Channel Display Engine MCDE RX + 11: UART port 2 + 12: UART port 1 + 13: UART port 0 + 14: Multirate Serial Port MSP2 + 15: I2C port 0 + 16: USB OTG in/out endpoints 7 & 15 + 17: USB OTG in/out endpoints 6 & 14 + 18: USB OTG in/out endpoints 5 & 13 + 19: USB OTG in/out endpoints 4 & 12 + 20: SLIMbus or HSI channel 0 + 21: SLIMbus or HSI channel 1 + 22: SLIMbus or HSI channel 2 + 23: SLIMbus or HSI channel 3 + 24: Multimedia DSP SXA0 + 25: Multimedia DSP SXA1 + 26: Multimedia DSP SXA2 + 27: Multimedia DSP SXA3 + 28: SD/MMC controller 2 + 29: SD/MMC controller 0 + 30: MSP port 1 on DB8500 v1, MSP port 3 on DB8500 v2 + 31: MSP port 0 or SLIMbus channel 0 + 32: SD/MMC controller 1 + 33: SPI controller 2 + 34: i2c3 RX2 TX2 + 35: SPI controller 1 + 36: USB OTG in/out endpoints 3 & 11 + 37: USB OTG in/out endpoints 2 & 10 + 38: USB OTG in/out endpoints 1 & 9 + 39: USB OTG in/out endpoints 8 + 40: SPI controller 3 + 41: SD/MMC controller 3 + 42: SD/MMC controller 4 + 43: SD/MMC controller 5 + 44: Multimedia DSP SXA4 + 45: Multimedia DSP SXA5 + 46: SLIMbus channel 8 or Multimedia DSP SXA6 + 47: SLIMbus channel 9 or Multimedia DSP SXA7 + 48: Crypto Accelerator 1 + 49: Crypto Accelerator 1 TX or Hash Accelerator 1 TX + 50: Hash Accelerator 1 TX + 51: memcpy TX (to be used by the DMA driver for memcpy operations) + 52: SLIMbus or HSI channel 4 + 53: SLIMbus or HSI channel 5 + 54: SLIMbus or HSI channel 6 + 55: SLIMbus or HSI channel 7 + 56: memcpy (to be used by the DMA driver for memcpy operations) + 57: memcpy (to be used by the DMA driver for memcpy operations) + 58: memcpy (to be used by the DMA driver for memcpy operations) + 59: memcpy (to be used by the DMA driver for memcpy operations) + 60: memcpy (to be used by the DMA driver for memcpy operations) + 61: Crypto Accelerator 0 + 62: Crypto Accelerator 0 TX or Hash Accelerator 0 TX + 63: Hash Accelerator 0 TX + + The second cell is the DMA request line number. This is only used when + a fixed channel is allocated, and indicated by setting bit 3 in the + flags field (see below). + + The third cell is a 32bit flags bitfield with the following possible + bits set: + 0x00000001 (bit 0) - mode: + Logical channel when unset + Physical channel when set + 0x00000002 (bit 1) - direction: + Memory to Device when unset + Device to Memory when set + 0x00000004 (bit 2) - endianness: + Little endian when unset + Big endian when set + 0x00000008 (bit 3) - use fixed channel: + Use automatic channel selection when unset + Use DMA request line number when set + 0x00000010 (bit 4) - set channel as high priority: + Normal priority when unset + High priority when set + + compatible: + items: + - const: stericsson,db8500-dma40 + - const: stericsson,dma40 + + reg: + items: + - description: DMA40 memory base + - description: LCPA memory base + + reg-names: + items: + - const: base + - const: lcpa + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + memcpy-channels: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: Array of u32 elements indicating which channels on the DMA + engine are elegible for memcpy transfers + +required: + - "#dma-cells" + - compatible + - reg + - interrupts + - clocks + - memcpy-channels + +additionalProperties: false + +examples: + - | + #include + #include + #include + dma-controller@801C0000 { + compatible = "stericsson,db8500-dma40", "stericsson,dma40"; + reg = <0x801C0000 0x1000>, <0x40010000 0x800>; + reg-names = "base", "lcpa"; + interrupts = ; + #dma-cells = <3>; + memcpy-channels = <56 57 58 59 60>; + clocks = <&prcmu_clk PRCMU_DMACLK>; + }; +... -- cgit v1.2.3 From 873971f8fb080d9d65865650fb43d5b9ee9a0d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 31 May 2022 23:36:13 +0200 Subject: dt-bindings: dma: Add Apple ADMAC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apple's Audio DMA Controller (ADMAC) is used to fetch and store audio samples on SoCs from the "Apple Silicon" family. Reviewed-by: Rob Herring Signed-off-by: Martin Povišer Link: https://lore.kernel.org/r/20220531213615.7822-2-povik+lin@cutebit.org Signed-off-by: Vinod Koul --- .../devicetree/bindings/dma/apple,admac.yaml | 75 ++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/apple,admac.yaml diff --git a/Documentation/devicetree/bindings/dma/apple,admac.yaml b/Documentation/devicetree/bindings/dma/apple,admac.yaml new file mode 100644 index 000000000000..ab8a4ec7779f --- /dev/null +++ b/Documentation/devicetree/bindings/dma/apple,admac.yaml @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/apple,admac.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Apple Audio DMA Controller (ADMAC) + +description: | + Apple's Audio DMA Controller (ADMAC) is used to fetch and store audio samples + on SoCs from the "Apple Silicon" family. + + The controller has been seen with up to 24 channels. Even-numbered channels + are TX-only, odd-numbered are RX-only. Individual channels are coupled to + fixed device endpoints. + +maintainers: + - Martin Povišer + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + compatible: + items: + - enum: + - apple,t6000-admac + - apple,t8103-admac + - const: apple,admac + + reg: + maxItems: 1 + + '#dma-cells': + const: 1 + description: + Clients specify a single cell with channel number. + + dma-channels: + maximum: 24 + + interrupts: + minItems: 4 + maxItems: 4 + description: + Interrupts that correspond to the 4 IRQ outputs of the controller. Usually + only one of the controller outputs will be connected as an usable interrupt + source. The remaining interrupts will be left without a valid value, e.g. + in an interrupts-extended list the disconnected positions will contain + an empty phandle reference <0>. + +required: + - compatible + - reg + - '#dma-cells' + - dma-channels + - interrupts + +additionalProperties: false + +examples: + - | + #include + #include + + admac: dma-controller@238200000 { + compatible = "apple,t8103-admac", "apple,admac"; + reg = <0x38200000 0x34000>; + dma-channels = <24>; + interrupts-extended = <0>, + <&aic AIC_IRQ 626 IRQ_TYPE_LEVEL_HIGH>, + <0>, + <0>; + #dma-cells = <1>; + }; -- cgit v1.2.3 From b127315d9a78c011c011b88b92f650510edcfbd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 31 May 2022 23:36:14 +0200 Subject: dmaengine: apple-admac: Add Apple ADMAC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add driver for Audio DMA Controller present on Apple SoCs from the "Apple Silicon" family. Signed-off-by: Martin Povišer Link: https://lore.kernel.org/r/20220531213615.7822-3-povik+lin@cutebit.org Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 8 + drivers/dma/Makefile | 1 + drivers/dma/apple-admac.c | 818 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 827 insertions(+) create mode 100644 drivers/dma/apple-admac.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 487ed4ddc3be..a06d2a7627aa 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -85,6 +85,14 @@ config AMCC_PPC440SPE_ADMA help Enable support for the AMCC PPC440SPe RAID engines. +config APPLE_ADMAC + tristate "Apple ADMAC support" + depends on ARCH_APPLE || COMPILE_TEST + select DMA_ENGINE + default ARCH_APPLE + help + Enable support for Audio DMA Controller found on Apple Silicon SoCs. + config AT_HDMAC tristate "Atmel AHB DMA support" depends on ARCH_AT91 diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 2f1b87ffd7ab..10f7d4241001 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_ALTERA_MSGDMA) += altera-msgdma.o obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/ obj-$(CONFIG_AMD_PTDMA) += ptdma/ +obj-$(CONFIG_APPLE_ADMAC) += apple-admac.o obj-$(CONFIG_AT_HDMAC) += at_hdmac.o obj-$(CONFIG_AT_XDMAC) += at_xdmac.o obj-$(CONFIG_AXI_DMAC) += dma-axi-dmac.o diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c new file mode 100644 index 000000000000..2425069c186d --- /dev/null +++ b/drivers/dma/apple-admac.c @@ -0,0 +1,818 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver for Audio DMA Controller (ADMAC) on t8103 (M1) and other Apple chips + * + * Copyright (C) The Asahi Linux Contributors + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dmaengine.h" + +#define NCHANNELS_MAX 64 +#define IRQ_NOUTPUTS 4 + +#define RING_WRITE_SLOT GENMASK(1, 0) +#define RING_READ_SLOT GENMASK(5, 4) +#define RING_FULL BIT(9) +#define RING_EMPTY BIT(8) +#define RING_ERR BIT(10) + +#define STATUS_DESC_DONE BIT(0) +#define STATUS_ERR BIT(6) + +#define FLAG_DESC_NOTIFY BIT(16) + +#define REG_TX_START 0x0000 +#define REG_TX_STOP 0x0004 +#define REG_RX_START 0x0008 +#define REG_RX_STOP 0x000c + +#define REG_CHAN_CTL(ch) (0x8000 + (ch) * 0x200) +#define REG_CHAN_CTL_RST_RINGS BIT(0) + +#define REG_DESC_RING(ch) (0x8070 + (ch) * 0x200) +#define REG_REPORT_RING(ch) (0x8074 + (ch) * 0x200) + +#define REG_RESIDUE(ch) (0x8064 + (ch) * 0x200) + +#define REG_BUS_WIDTH(ch) (0x8040 + (ch) * 0x200) + +#define BUS_WIDTH_8BIT 0x00 +#define BUS_WIDTH_16BIT 0x01 +#define BUS_WIDTH_32BIT 0x02 +#define BUS_WIDTH_FRAME_2_WORDS 0x10 +#define BUS_WIDTH_FRAME_4_WORDS 0x20 + +#define CHAN_BUFSIZE 0x8000 + +#define REG_CHAN_FIFOCTL(ch) (0x8054 + (ch) * 0x200) +#define CHAN_FIFOCTL_LIMIT GENMASK(31, 16) +#define CHAN_FIFOCTL_THRESHOLD GENMASK(15, 0) + +#define REG_DESC_WRITE(ch) (0x10000 + ((ch) / 2) * 0x4 + ((ch) & 1) * 0x4000) +#define REG_REPORT_READ(ch) (0x10100 + ((ch) / 2) * 0x4 + ((ch) & 1) * 0x4000) + +#define REG_TX_INTSTATE(idx) (0x0030 + (idx) * 4) +#define REG_RX_INTSTATE(idx) (0x0040 + (idx) * 4) +#define REG_CHAN_INTSTATUS(ch, idx) (0x8010 + (ch) * 0x200 + (idx) * 4) +#define REG_CHAN_INTMASK(ch, idx) (0x8020 + (ch) * 0x200 + (idx) * 4) + +struct admac_data; +struct admac_tx; + +struct admac_chan { + unsigned int no; + struct admac_data *host; + struct dma_chan chan; + struct tasklet_struct tasklet; + + spinlock_t lock; + struct admac_tx *current_tx; + int nperiod_acks; + + /* + * We maintain a 'submitted' and 'issued' list mainly for interface + * correctness. Typical use of the driver (per channel) will be + * prepping, submitting and issuing a single cyclic transaction which + * will stay current until terminate_all is called. + */ + struct list_head submitted; + struct list_head issued; + + struct list_head to_free; +}; + +struct admac_data { + struct dma_device dma; + struct device *dev; + __iomem void *base; + + int irq_index; + int nchannels; + struct admac_chan channels[]; +}; + +struct admac_tx { + struct dma_async_tx_descriptor tx; + bool cyclic; + dma_addr_t buf_addr; + dma_addr_t buf_end; + size_t buf_len; + size_t period_len; + + size_t submitted_pos; + size_t reclaimed_pos; + + struct list_head node; +}; + +static void admac_modify(struct admac_data *ad, int reg, u32 mask, u32 val) +{ + void __iomem *addr = ad->base + reg; + u32 curr = readl_relaxed(addr); + + writel_relaxed((curr & ~mask) | (val & mask), addr); +} + +static struct admac_chan *to_admac_chan(struct dma_chan *chan) +{ + return container_of(chan, struct admac_chan, chan); +} + +static struct admac_tx *to_admac_tx(struct dma_async_tx_descriptor *tx) +{ + return container_of(tx, struct admac_tx, tx); +} + +static enum dma_transfer_direction admac_chan_direction(int channo) +{ + /* Channel directions are hardwired */ + return (channo & 1) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; +} + +static dma_cookie_t admac_tx_submit(struct dma_async_tx_descriptor *tx) +{ + struct admac_tx *adtx = to_admac_tx(tx); + struct admac_chan *adchan = to_admac_chan(tx->chan); + unsigned long flags; + dma_cookie_t cookie; + + spin_lock_irqsave(&adchan->lock, flags); + cookie = dma_cookie_assign(tx); + list_add_tail(&adtx->node, &adchan->submitted); + spin_unlock_irqrestore(&adchan->lock, flags); + + return cookie; +} + +static int admac_desc_free(struct dma_async_tx_descriptor *tx) +{ + kfree(to_admac_tx(tx)); + + return 0; +} + +static struct dma_async_tx_descriptor *admac_prep_dma_cyclic( + struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction direction, + unsigned long flags) +{ + struct admac_chan *adchan = container_of(chan, struct admac_chan, chan); + struct admac_tx *adtx; + + if (direction != admac_chan_direction(adchan->no)) + return NULL; + + adtx = kzalloc(sizeof(*adtx), GFP_NOWAIT); + if (!adtx) + return NULL; + + adtx->cyclic = true; + + adtx->buf_addr = buf_addr; + adtx->buf_len = buf_len; + adtx->buf_end = buf_addr + buf_len; + adtx->period_len = period_len; + + adtx->submitted_pos = 0; + adtx->reclaimed_pos = 0; + + dma_async_tx_descriptor_init(&adtx->tx, chan); + adtx->tx.tx_submit = admac_tx_submit; + adtx->tx.desc_free = admac_desc_free; + + return &adtx->tx; +} + +/* + * Write one hardware descriptor for a dmaengine cyclic transaction. + */ +static void admac_cyclic_write_one_desc(struct admac_data *ad, int channo, + struct admac_tx *tx) +{ + dma_addr_t addr; + + addr = tx->buf_addr + (tx->submitted_pos % tx->buf_len); + + /* If happens means we have buggy code */ + WARN_ON_ONCE(addr + tx->period_len > tx->buf_end); + + dev_dbg(ad->dev, "ch%d descriptor: addr=0x%pad len=0x%zx flags=0x%x\n", + channo, &addr, tx->period_len, FLAG_DESC_NOTIFY); + + writel_relaxed(addr, ad->base + REG_DESC_WRITE(channo)); + writel_relaxed(addr >> 32, ad->base + REG_DESC_WRITE(channo)); + writel_relaxed(tx->period_len, ad->base + REG_DESC_WRITE(channo)); + writel_relaxed(FLAG_DESC_NOTIFY, ad->base + REG_DESC_WRITE(channo)); + + tx->submitted_pos += tx->period_len; + tx->submitted_pos %= 2 * tx->buf_len; +} + +/* + * Write all the hardware descriptors for a dmaengine cyclic + * transaction there is space for. + */ +static void admac_cyclic_write_desc(struct admac_data *ad, int channo, + struct admac_tx *tx) +{ + int i; + + for (i = 0; i < 4; i++) { + if (readl_relaxed(ad->base + REG_DESC_RING(channo)) & RING_FULL) + break; + admac_cyclic_write_one_desc(ad, channo, tx); + } +} + +static int admac_ring_noccupied_slots(int ringval) +{ + int wrslot = FIELD_GET(RING_WRITE_SLOT, ringval); + int rdslot = FIELD_GET(RING_READ_SLOT, ringval); + + if (wrslot != rdslot) { + return (wrslot + 4 - rdslot) % 4; + } else { + WARN_ON((ringval & (RING_FULL | RING_EMPTY)) == 0); + + if (ringval & RING_FULL) + return 4; + else + return 0; + } +} + +/* + * Read from hardware the residue of a cyclic dmaengine transaction. + */ +static u32 admac_cyclic_read_residue(struct admac_data *ad, int channo, + struct admac_tx *adtx) +{ + u32 ring1, ring2; + u32 residue1, residue2; + int nreports; + size_t pos; + + ring1 = readl_relaxed(ad->base + REG_REPORT_RING(channo)); + residue1 = readl_relaxed(ad->base + REG_RESIDUE(channo)); + ring2 = readl_relaxed(ad->base + REG_REPORT_RING(channo)); + residue2 = readl_relaxed(ad->base + REG_RESIDUE(channo)); + + if (residue2 > residue1) { + /* + * Controller must have loaded next descriptor between + * the two residue reads + */ + nreports = admac_ring_noccupied_slots(ring1) + 1; + } else { + /* No descriptor load between the two reads, ring2 is safe to use */ + nreports = admac_ring_noccupied_slots(ring2); + } + + pos = adtx->reclaimed_pos + adtx->period_len * (nreports + 1) - residue2; + + return adtx->buf_len - pos % adtx->buf_len; +} + +static enum dma_status admac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, + struct dma_tx_state *txstate) +{ + struct admac_chan *adchan = to_admac_chan(chan); + struct admac_data *ad = adchan->host; + struct admac_tx *adtx; + + enum dma_status ret; + size_t residue; + unsigned long flags; + + ret = dma_cookie_status(chan, cookie, txstate); + if (ret == DMA_COMPLETE || !txstate) + return ret; + + spin_lock_irqsave(&adchan->lock, flags); + adtx = adchan->current_tx; + + if (adtx && adtx->tx.cookie == cookie) { + ret = DMA_IN_PROGRESS; + residue = admac_cyclic_read_residue(ad, adchan->no, adtx); + } else { + ret = DMA_IN_PROGRESS; + residue = 0; + list_for_each_entry(adtx, &adchan->issued, node) { + if (adtx->tx.cookie == cookie) { + residue = adtx->buf_len; + break; + } + } + } + spin_unlock_irqrestore(&adchan->lock, flags); + + dma_set_residue(txstate, residue); + return ret; +} + +static void admac_start_chan(struct admac_chan *adchan) +{ + struct admac_data *ad = adchan->host; + u32 startbit = 1 << (adchan->no / 2); + + writel_relaxed(STATUS_DESC_DONE | STATUS_ERR, + ad->base + REG_CHAN_INTSTATUS(adchan->no, ad->irq_index)); + writel_relaxed(STATUS_DESC_DONE | STATUS_ERR, + ad->base + REG_CHAN_INTMASK(adchan->no, ad->irq_index)); + + switch (admac_chan_direction(adchan->no)) { + case DMA_MEM_TO_DEV: + writel_relaxed(startbit, ad->base + REG_TX_START); + break; + case DMA_DEV_TO_MEM: + writel_relaxed(startbit, ad->base + REG_RX_START); + break; + default: + break; + } + dev_dbg(adchan->host->dev, "ch%d start\n", adchan->no); +} + +static void admac_stop_chan(struct admac_chan *adchan) +{ + struct admac_data *ad = adchan->host; + u32 stopbit = 1 << (adchan->no / 2); + + switch (admac_chan_direction(adchan->no)) { + case DMA_MEM_TO_DEV: + writel_relaxed(stopbit, ad->base + REG_TX_STOP); + break; + case DMA_DEV_TO_MEM: + writel_relaxed(stopbit, ad->base + REG_RX_STOP); + break; + default: + break; + } + dev_dbg(adchan->host->dev, "ch%d stop\n", adchan->no); +} + +static void admac_reset_rings(struct admac_chan *adchan) +{ + struct admac_data *ad = adchan->host; + + writel_relaxed(REG_CHAN_CTL_RST_RINGS, + ad->base + REG_CHAN_CTL(adchan->no)); + writel_relaxed(0, ad->base + REG_CHAN_CTL(adchan->no)); +} + +static void admac_start_current_tx(struct admac_chan *adchan) +{ + struct admac_data *ad = adchan->host; + int ch = adchan->no; + + admac_reset_rings(adchan); + writel_relaxed(0, ad->base + REG_CHAN_CTL(ch)); + + admac_cyclic_write_one_desc(ad, ch, adchan->current_tx); + admac_start_chan(adchan); + admac_cyclic_write_desc(ad, ch, adchan->current_tx); +} + +static void admac_issue_pending(struct dma_chan *chan) +{ + struct admac_chan *adchan = to_admac_chan(chan); + struct admac_tx *tx; + unsigned long flags; + + spin_lock_irqsave(&adchan->lock, flags); + list_splice_tail_init(&adchan->submitted, &adchan->issued); + if (!list_empty(&adchan->issued) && !adchan->current_tx) { + tx = list_first_entry(&adchan->issued, struct admac_tx, node); + list_del(&tx->node); + + adchan->current_tx = tx; + adchan->nperiod_acks = 0; + admac_start_current_tx(adchan); + } + spin_unlock_irqrestore(&adchan->lock, flags); +} + +static int admac_pause(struct dma_chan *chan) +{ + struct admac_chan *adchan = to_admac_chan(chan); + + admac_stop_chan(adchan); + + return 0; +} + +static int admac_resume(struct dma_chan *chan) +{ + struct admac_chan *adchan = to_admac_chan(chan); + + admac_start_chan(adchan); + + return 0; +} + +static int admac_terminate_all(struct dma_chan *chan) +{ + struct admac_chan *adchan = to_admac_chan(chan); + unsigned long flags; + + spin_lock_irqsave(&adchan->lock, flags); + admac_stop_chan(adchan); + admac_reset_rings(adchan); + + adchan->current_tx = NULL; + /* + * Descriptors can only be freed after the tasklet + * has been killed (in admac_synchronize). + */ + list_splice_tail_init(&adchan->submitted, &adchan->to_free); + list_splice_tail_init(&adchan->issued, &adchan->to_free); + spin_unlock_irqrestore(&adchan->lock, flags); + + return 0; +} + +static void admac_synchronize(struct dma_chan *chan) +{ + struct admac_chan *adchan = to_admac_chan(chan); + struct admac_tx *adtx, *_adtx; + unsigned long flags; + LIST_HEAD(head); + + spin_lock_irqsave(&adchan->lock, flags); + list_splice_tail_init(&adchan->to_free, &head); + spin_unlock_irqrestore(&adchan->lock, flags); + + tasklet_kill(&adchan->tasklet); + + list_for_each_entry_safe(adtx, _adtx, &head, node) { + list_del(&adtx->node); + admac_desc_free(&adtx->tx); + } +} + +static int admac_alloc_chan_resources(struct dma_chan *chan) +{ + struct admac_chan *adchan = to_admac_chan(chan); + + dma_cookie_init(&adchan->chan); + return 0; +} + +static void admac_free_chan_resources(struct dma_chan *chan) +{ + admac_terminate_all(chan); + admac_synchronize(chan); +} + +static struct dma_chan *admac_dma_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct admac_data *ad = (struct admac_data *) ofdma->of_dma_data; + unsigned int index; + + if (dma_spec->args_count != 1) + return NULL; + + index = dma_spec->args[0]; + + if (index >= ad->nchannels) { + dev_err(ad->dev, "channel index %u out of bounds\n", index); + return NULL; + } + + return &ad->channels[index].chan; +} + +static int admac_drain_reports(struct admac_data *ad, int channo) +{ + int count; + + for (count = 0; count < 4; count++) { + u32 countval_hi, countval_lo, unk1, flags; + + if (readl_relaxed(ad->base + REG_REPORT_RING(channo)) & RING_EMPTY) + break; + + countval_lo = readl_relaxed(ad->base + REG_REPORT_READ(channo)); + countval_hi = readl_relaxed(ad->base + REG_REPORT_READ(channo)); + unk1 = readl_relaxed(ad->base + REG_REPORT_READ(channo)); + flags = readl_relaxed(ad->base + REG_REPORT_READ(channo)); + + dev_dbg(ad->dev, "ch%d report: countval=0x%llx unk1=0x%x flags=0x%x\n", + channo, ((u64) countval_hi) << 32 | countval_lo, unk1, flags); + } + + return count; +} + +static void admac_handle_status_err(struct admac_data *ad, int channo) +{ + bool handled = false; + + if (readl_relaxed(ad->base + REG_DESC_RING(channo)) & RING_ERR) { + writel_relaxed(RING_ERR, ad->base + REG_DESC_RING(channo)); + dev_err_ratelimited(ad->dev, "ch%d descriptor ring error\n", channo); + handled = true; + } + + if (readl_relaxed(ad->base + REG_REPORT_RING(channo)) & RING_ERR) { + writel_relaxed(RING_ERR, ad->base + REG_REPORT_RING(channo)); + dev_err_ratelimited(ad->dev, "ch%d report ring error\n", channo); + handled = true; + } + + if (unlikely(!handled)) { + dev_err(ad->dev, "ch%d unknown error, masking errors as cause of IRQs\n", channo); + admac_modify(ad, REG_CHAN_INTMASK(channo, ad->irq_index), + STATUS_ERR, 0); + } +} + +static void admac_handle_status_desc_done(struct admac_data *ad, int channo) +{ + struct admac_chan *adchan = &ad->channels[channo]; + unsigned long flags; + int nreports; + + writel_relaxed(STATUS_DESC_DONE, + ad->base + REG_CHAN_INTSTATUS(channo, ad->irq_index)); + + spin_lock_irqsave(&adchan->lock, flags); + nreports = admac_drain_reports(ad, channo); + + if (adchan->current_tx) { + struct admac_tx *tx = adchan->current_tx; + + adchan->nperiod_acks += nreports; + tx->reclaimed_pos += nreports * tx->period_len; + tx->reclaimed_pos %= 2 * tx->buf_len; + + admac_cyclic_write_desc(ad, channo, tx); + tasklet_schedule(&adchan->tasklet); + } + spin_unlock_irqrestore(&adchan->lock, flags); +} + +static void admac_handle_chan_int(struct admac_data *ad, int no) +{ + u32 cause = readl_relaxed(ad->base + REG_CHAN_INTSTATUS(no, ad->irq_index)); + + if (cause & STATUS_ERR) + admac_handle_status_err(ad, no); + + if (cause & STATUS_DESC_DONE) + admac_handle_status_desc_done(ad, no); +} + +static irqreturn_t admac_interrupt(int irq, void *devid) +{ + struct admac_data *ad = devid; + u32 rx_intstate, tx_intstate; + int i; + + rx_intstate = readl_relaxed(ad->base + REG_RX_INTSTATE(ad->irq_index)); + tx_intstate = readl_relaxed(ad->base + REG_TX_INTSTATE(ad->irq_index)); + + if (!tx_intstate && !rx_intstate) + return IRQ_NONE; + + for (i = 0; i < ad->nchannels; i += 2) { + if (tx_intstate & 1) + admac_handle_chan_int(ad, i); + tx_intstate >>= 1; + } + + for (i = 1; i < ad->nchannels; i += 2) { + if (rx_intstate & 1) + admac_handle_chan_int(ad, i); + rx_intstate >>= 1; + } + + return IRQ_HANDLED; +} + +static void admac_chan_tasklet(struct tasklet_struct *t) +{ + struct admac_chan *adchan = from_tasklet(adchan, t, tasklet); + struct admac_tx *adtx; + struct dmaengine_desc_callback cb; + struct dmaengine_result tx_result; + int nacks; + + spin_lock_irq(&adchan->lock); + adtx = adchan->current_tx; + nacks = adchan->nperiod_acks; + adchan->nperiod_acks = 0; + spin_unlock_irq(&adchan->lock); + + if (!adtx || !nacks) + return; + + tx_result.result = DMA_TRANS_NOERROR; + tx_result.residue = 0; + + dmaengine_desc_get_callback(&adtx->tx, &cb); + while (nacks--) + dmaengine_desc_callback_invoke(&cb, &tx_result); +} + +static int admac_device_config(struct dma_chan *chan, + struct dma_slave_config *config) +{ + struct admac_chan *adchan = to_admac_chan(chan); + struct admac_data *ad = adchan->host; + bool is_tx = admac_chan_direction(adchan->no) == DMA_MEM_TO_DEV; + int wordsize = 0; + u32 bus_width = 0; + + switch (is_tx ? config->dst_addr_width : config->src_addr_width) { + case DMA_SLAVE_BUSWIDTH_1_BYTE: + wordsize = 1; + bus_width |= BUS_WIDTH_8BIT; + break; + case DMA_SLAVE_BUSWIDTH_2_BYTES: + wordsize = 2; + bus_width |= BUS_WIDTH_16BIT; + break; + case DMA_SLAVE_BUSWIDTH_4_BYTES: + wordsize = 4; + bus_width |= BUS_WIDTH_32BIT; + break; + default: + return -EINVAL; + } + + /* + * We take port_window_size to be the number of words in a frame. + * + * The controller has some means of out-of-band signalling, to the peripheral, + * of words position in a frame. That's where the importance of this control + * comes from. + */ + switch (is_tx ? config->dst_port_window_size : config->src_port_window_size) { + case 0 ... 1: + break; + case 2: + bus_width |= BUS_WIDTH_FRAME_2_WORDS; + break; + case 4: + bus_width |= BUS_WIDTH_FRAME_4_WORDS; + break; + default: + return -EINVAL; + } + + writel_relaxed(bus_width, ad->base + REG_BUS_WIDTH(adchan->no)); + + /* + * By FIFOCTL_LIMIT we seem to set the maximal number of bytes allowed to be + * held in controller's per-channel FIFO. Transfers seem to be triggered + * around the time FIFO occupancy touches FIFOCTL_THRESHOLD. + * + * The numbers we set are more or less arbitrary. + */ + writel_relaxed(FIELD_PREP(CHAN_FIFOCTL_LIMIT, 0x30 * wordsize) + | FIELD_PREP(CHAN_FIFOCTL_THRESHOLD, 0x18 * wordsize), + ad->base + REG_CHAN_FIFOCTL(adchan->no)); + + return 0; +} + +static int admac_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct admac_data *ad; + struct dma_device *dma; + int nchannels; + int err, irq, i; + + err = of_property_read_u32(np, "dma-channels", &nchannels); + if (err || nchannels > NCHANNELS_MAX) { + dev_err(&pdev->dev, "missing or invalid dma-channels property\n"); + return -EINVAL; + } + + ad = devm_kzalloc(&pdev->dev, struct_size(ad, channels, nchannels), GFP_KERNEL); + if (!ad) + return -ENOMEM; + + platform_set_drvdata(pdev, ad); + ad->dev = &pdev->dev; + ad->nchannels = nchannels; + + /* + * The controller has 4 IRQ outputs. Try them all until + * we find one we can use. + */ + for (i = 0; i < IRQ_NOUTPUTS; i++) { + irq = platform_get_irq_optional(pdev, i); + if (irq >= 0) { + ad->irq_index = i; + break; + } + } + + if (irq < 0) + return dev_err_probe(&pdev->dev, irq, "no usable interrupt\n"); + + err = devm_request_irq(&pdev->dev, irq, admac_interrupt, + 0, dev_name(&pdev->dev), ad); + if (err) + return dev_err_probe(&pdev->dev, err, + "unable to register interrupt\n"); + + ad->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ad->base)) + return dev_err_probe(&pdev->dev, PTR_ERR(ad->base), + "unable to obtain MMIO resource\n"); + + dma = &ad->dma; + + dma_cap_set(DMA_PRIVATE, dma->cap_mask); + dma_cap_set(DMA_CYCLIC, dma->cap_mask); + + dma->dev = &pdev->dev; + dma->device_alloc_chan_resources = admac_alloc_chan_resources; + dma->device_free_chan_resources = admac_free_chan_resources; + dma->device_tx_status = admac_tx_status; + dma->device_issue_pending = admac_issue_pending; + dma->device_terminate_all = admac_terminate_all; + dma->device_synchronize = admac_synchronize; + dma->device_prep_dma_cyclic = admac_prep_dma_cyclic; + dma->device_config = admac_device_config; + dma->device_pause = admac_pause; + dma->device_resume = admac_resume; + + dma->directions = BIT(DMA_MEM_TO_DEV) | BIT(DMA_DEV_TO_MEM); + dma->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + dma->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + + INIT_LIST_HEAD(&dma->channels); + for (i = 0; i < nchannels; i++) { + struct admac_chan *adchan = &ad->channels[i]; + + adchan->host = ad; + adchan->no = i; + adchan->chan.device = &ad->dma; + spin_lock_init(&adchan->lock); + INIT_LIST_HEAD(&adchan->submitted); + INIT_LIST_HEAD(&adchan->issued); + INIT_LIST_HEAD(&adchan->to_free); + list_add_tail(&adchan->chan.device_node, &dma->channels); + tasklet_setup(&adchan->tasklet, admac_chan_tasklet); + } + + err = dma_async_device_register(&ad->dma); + if (err) + return dev_err_probe(&pdev->dev, err, "failed to register DMA device\n"); + + err = of_dma_controller_register(pdev->dev.of_node, admac_dma_of_xlate, ad); + if (err) { + dma_async_device_unregister(&ad->dma); + return dev_err_probe(&pdev->dev, err, "failed to register with OF\n"); + } + + return 0; +} + +static int admac_remove(struct platform_device *pdev) +{ + struct admac_data *ad = platform_get_drvdata(pdev); + + of_dma_controller_free(pdev->dev.of_node); + dma_async_device_unregister(&ad->dma); + + return 0; +} + +static const struct of_device_id admac_of_match[] = { + { .compatible = "apple,admac", }, + { } +}; +MODULE_DEVICE_TABLE(of, admac_of_match); + +static struct platform_driver apple_admac_driver = { + .driver = { + .name = "apple-admac", + .of_match_table = admac_of_match, + }, + .probe = admac_probe, + .remove = admac_remove, +}; +module_platform_driver(apple_admac_driver); + +MODULE_AUTHOR("Martin Povišer "); +MODULE_DESCRIPTION("Driver for Audio DMA Controller (ADMAC) on Apple SoCs"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From cb4e34856b77ff52f2b18e0554d364b558f9b258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 31 May 2022 23:36:15 +0200 Subject: MAINTAINERS: Add ADMAC driver under ARM/APPLE MACHINE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Register the driver source and binding schema. Signed-off-by: Martin Povišer Link: https://lore.kernel.org/r/20220531213615.7822-4-povik+lin@cutebit.org Signed-off-by: Vinod Koul --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index a6d3bd9d2a8d..71eec7842ec6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1832,6 +1832,7 @@ T: git https://github.com/AsahiLinux/linux.git F: Documentation/devicetree/bindings/arm/apple.yaml F: Documentation/devicetree/bindings/arm/apple/* F: Documentation/devicetree/bindings/clock/apple,nco.yaml +F: Documentation/devicetree/bindings/dma/apple,admac.yaml F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml F: Documentation/devicetree/bindings/interrupt-controller/apple,* F: Documentation/devicetree/bindings/iommu/apple,dart.yaml @@ -1845,6 +1846,7 @@ F: Documentation/devicetree/bindings/power/apple* F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml F: arch/arm64/boot/dts/apple/ F: drivers/clk/clk-apple-nco.c +F: drivers/dma/apple-admac.c F: drivers/i2c/busses/i2c-pasemi-core.c F: drivers/i2c/busses/i2c-pasemi-platform.c F: drivers/iommu/apple-dart.c -- cgit v1.2.3 From 11a72ae911d3d4eccfba8dbf21daca4ce5f1b6af Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 10 Jun 2022 10:01:17 +0530 Subject: dmaengine: apple-admac: Fix print format We get a warning (treated as error now) drivers/dma/apple-admac.c: In function 'admac_cyclic_write_one_desc': drivers/dma/apple-admac.c:209:26: error: format '%x' expects argument of type 'unsigned int', but argument 7 has type 'long unsigned int' [-Werror=format=] 209 | dev_dbg(ad->dev, "ch%d descriptor: addr=0x%pad len=0x%zx flags=0x%x\n", Use %lx for priniting the flag Fixes: b127315d9a78 ("dmaengine: apple-admac: Add Apple ADMAC driver") Reported-by: Stephen Rothwell Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20220610043117.39337-1-vkoul@kernel.org Reported-by: kernel test robot Signed-off-by: Vinod Koul --- drivers/dma/apple-admac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c index 2425069c186d..c502f8c3aca7 100644 --- a/drivers/dma/apple-admac.c +++ b/drivers/dma/apple-admac.c @@ -206,7 +206,7 @@ static void admac_cyclic_write_one_desc(struct admac_data *ad, int channo, /* If happens means we have buggy code */ WARN_ON_ONCE(addr + tx->period_len > tx->buf_end); - dev_dbg(ad->dev, "ch%d descriptor: addr=0x%pad len=0x%zx flags=0x%x\n", + dev_dbg(ad->dev, "ch%d descriptor: addr=0x%pad len=0x%zx flags=0x%lx\n", channo, &addr, tx->period_len, FLAG_DESC_NOTIFY); writel_relaxed(addr, ad->base + REG_DESC_WRITE(channo)); -- cgit v1.2.3 From 2717d33841957a0f5fb65fd8b37f9c2321593864 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Thu, 9 Jun 2022 16:14:54 +0200 Subject: dmaengine: dw: dmamux: Export the module device table This is a tristate driver that can be built as a module, as a result, the OF match table should be exported with MODULE_DEVICE_TABLE(). Fixes: 134d9c52fca2 ("dmaengine: dw: dmamux: Introduce RZN1 DMA router support") Signed-off-by: Miquel Raynal Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220609141455.300879-1-miquel.raynal@bootlin.com Signed-off-by: Vinod Koul --- drivers/dma/dw/rzn1-dmamux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/dw/rzn1-dmamux.c b/drivers/dma/dw/rzn1-dmamux.c index 11d254e450b0..0ce4fb58185e 100644 --- a/drivers/dma/dw/rzn1-dmamux.c +++ b/drivers/dma/dw/rzn1-dmamux.c @@ -140,6 +140,7 @@ static const struct of_device_id rzn1_dmamux_match[] = { { .compatible = "renesas,rzn1-dmamux" }, {} }; +MODULE_DEVICE_TABLE(of, rzn1_dmamux_match); static struct platform_driver rzn1_dmamux_driver = { .driver = { -- cgit v1.2.3 From 7811f2e7fd6a30d96eaa1fccf57b07694a8cad27 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Thu, 9 Jun 2022 16:14:55 +0200 Subject: dmaengine: dw: dmamux: Fix build without CONFIG_OF When built without OF support, of_match_node() expands to NULL, which produces the following output: >> drivers/dma/dw/rzn1-dmamux.c:105:34: warning: unused variable 'rzn1_dmac_match' [-Wunused-const-variable] static const struct of_device_id rzn1_dmac_match[] = { One way to silence the warning is to enclose the structure definition with an #ifdef CONFIG_OF/#endif block. Fixes: 134d9c52fca2 ("dmaengine: dw: dmamux: Introduce RZN1 DMA router support") Reported-by: kernel test robot Signed-off-by: Miquel Raynal Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220609141455.300879-2-miquel.raynal@bootlin.com Signed-off-by: Vinod Koul --- drivers/dma/dw/rzn1-dmamux.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/dw/rzn1-dmamux.c b/drivers/dma/dw/rzn1-dmamux.c index 0ce4fb58185e..f9912c3dd4d7 100644 --- a/drivers/dma/dw/rzn1-dmamux.c +++ b/drivers/dma/dw/rzn1-dmamux.c @@ -102,10 +102,12 @@ free_map: return ERR_PTR(ret); } +#ifdef CONFIG_OF static const struct of_device_id rzn1_dmac_match[] = { { .compatible = "renesas,rzn1-dma" }, {} }; +#endif static int rzn1_dmamux_probe(struct platform_device *pdev) { -- cgit v1.2.3 From c9357195c5770029f0c65a5b76756dea5b767ff0 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Fri, 10 Jun 2022 13:07:00 +0300 Subject: dmaengine: dw-edma: remove a macro conditional with similar branches After adding commit 8fc5133d6d4d ("dmaengine: dw-edma: Fix unaligned 64bit access") two branches under macro conditional become identical, thus the code can be simplified without any functional change. Signed-off-by: Vladimir Zapolskiy Acked-by: Herve Codina Link: https://lore.kernel.org/r/20220610100700.2295522-1-vladimir.zapolskiy@linaro.org Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-v0-core.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index 33bc1e6c4cf2..c73b9ed1ce74 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -414,19 +414,11 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first) SET_CH_32(dw, chan->dir, chan->id, ch_control1, (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE)); /* Linked list */ - - #ifdef CONFIG_64BIT /* llp is not aligned on 64bit -> keep 32bit accesses */ SET_CH_32(dw, chan->dir, chan->id, llp.lsb, lower_32_bits(chunk->ll_region.paddr)); SET_CH_32(dw, chan->dir, chan->id, llp.msb, upper_32_bits(chunk->ll_region.paddr)); - #else /* CONFIG_64BIT */ - SET_CH_32(dw, chan->dir, chan->id, llp.lsb, - lower_32_bits(chunk->ll_region.paddr)); - SET_CH_32(dw, chan->dir, chan->id, llp.msb, - upper_32_bits(chunk->ll_region.paddr)); - #endif /* CONFIG_64BIT */ } /* Doorbell */ SET_RW_32(dw, chan->dir, doorbell, -- cgit v1.2.3 From 62c427ca0745d54c7b715923633ced3e34453722 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 14 Jun 2022 09:25:03 -0600 Subject: dt-bindings: dma: apple,admac: Fix example interrupt parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 873971f8fb08 ("dt-bindings: dma: Add Apple ADMAC") has a warning in its example: Documentation/devicetree/bindings/dma/apple,admac.example.dtb: dma-controller@238200000: interrupts-extended: [[0], [4294967295, 0, 626, 4, 0, 0]] is too short From schema: /builds/robherring/linux-dt/Documentation/devicetree/bindings/dma/apple,admac.yaml The problem is the number of interrupt cells can't be guessed when there are empty '0' entries. So the example must have a valid interrupt controller defining the number of interrupt cells. Fixes: 873971f8fb08 ("dt-bindings: dma: Add Apple ADMAC") Signed-off-by: Rob Herring Acked-by: Martin Povišer Link: https://lore.kernel.org/r/20220614152503.1410755-1-robh@kernel.org Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/apple,admac.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/dma/apple,admac.yaml b/Documentation/devicetree/bindings/dma/apple,admac.yaml index ab8a4ec7779f..bdc8c129c4f5 100644 --- a/Documentation/devicetree/bindings/dma/apple,admac.yaml +++ b/Documentation/devicetree/bindings/dma/apple,admac.yaml @@ -63,6 +63,11 @@ examples: #include #include + aic: interrupt-controller { + interrupt-controller; + #interrupt-cells = <3>; + }; + admac: dma-controller@238200000 { compatible = "apple,t8103-admac", "apple,admac"; reg = <0x38200000 0x34000>; -- cgit v1.2.3 From 81ce6f3dbbdce2785bba6e0b3c540793725c218d Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Mon, 13 Jun 2022 13:03:26 +0200 Subject: MAINTAINERS: add include/dt-bindings/dma to DMA GENERIC OFFLOAD ENGINE SUBSYSTEM Maintainers of the directory Documentation/devicetree/bindings/dma are also the maintainers of the corresponding directory include/dt-bindings/dma. Add the file entry for include/dt-bindings/dma to the appropriate section in MAINTAINERS. Signed-off-by: Lukas Bulwahn Link: https://lore.kernel.org/r/20220613110326.18126-1-lukas.bulwahn@gmail.com Signed-off-by: Vinod Koul --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 71eec7842ec6..c9e1353788f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5948,6 +5948,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git F: Documentation/devicetree/bindings/dma/ F: Documentation/driver-api/dmaengine/ F: drivers/dma/ +F: include/dt-bindings/dma/ F: include/linux/dma/ F: include/linux/dmaengine.h F: include/linux/of_dma.h -- cgit v1.2.3 From ce4b461ba2c1247e0508995ff250f156b5310441 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 16 Jun 2022 16:13:12 +0200 Subject: dmaengine: apple-admac: Use {low,upp}er_32_bits() to split 64-bit address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_PHYS_ADDR_T_64BIT is not set: drivers/dma/apple-admac.c: In function ‘admac_cyclic_write_one_desc’: drivers/dma/apple-admac.c:213:22: error: right shift count >= width of type [-Werror=shift-count-overflow] 213 | writel_relaxed(addr >> 32, ad->base + REG_DESC_WRITE(channo)); | ^~ Fix this by using the {low,upp}er_32_bits() helper macros to obtain the address parts. Reported-by: noreply@ellerman.id.au Fixes: b127315d9a78c011 ("dmaengine: apple-admac: Add Apple ADMAC driver") Acked-by: Martin Povišer Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20220616141312.1953819-1-geert@linux-m68k.org Signed-off-by: Vinod Koul --- drivers/dma/apple-admac.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c index c502f8c3aca7..d1f74a3aa999 100644 --- a/drivers/dma/apple-admac.c +++ b/drivers/dma/apple-admac.c @@ -209,10 +209,10 @@ static void admac_cyclic_write_one_desc(struct admac_data *ad, int channo, dev_dbg(ad->dev, "ch%d descriptor: addr=0x%pad len=0x%zx flags=0x%lx\n", channo, &addr, tx->period_len, FLAG_DESC_NOTIFY); - writel_relaxed(addr, ad->base + REG_DESC_WRITE(channo)); - writel_relaxed(addr >> 32, ad->base + REG_DESC_WRITE(channo)); - writel_relaxed(tx->period_len, ad->base + REG_DESC_WRITE(channo)); - writel_relaxed(FLAG_DESC_NOTIFY, ad->base + REG_DESC_WRITE(channo)); + writel_relaxed(lower_32_bits(addr), ad->base + REG_DESC_WRITE(channo)); + writel_relaxed(upper_32_bits(addr), ad->base + REG_DESC_WRITE(channo)); + writel_relaxed(tx->period_len, ad->base + REG_DESC_WRITE(channo)); + writel_relaxed(FLAG_DESC_NOTIFY, ad->base + REG_DESC_WRITE(channo)); tx->submitted_pos += tx->period_len; tx->submitted_pos %= 2 * tx->buf_len; -- cgit v1.2.3 From 5dc8638872ef0deeae1371a9e2d551920870f76a Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 15 Jun 2022 16:26:51 -0700 Subject: MAINTAINERS: idxd driver maintainer update Add Fenghua as maintainer of the idxd driver. Signed-off-by: Fenghua Yu Signed-off-by: Dave Jiang Link: https://lore.kernel.org/r/20220615232651.177098-1-fenghua.yu@intel.com Signed-off-by: Vinod Koul --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index c9e1353788f2..d499b5783696 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9935,7 +9935,8 @@ S: Supported Q: https://patchwork.kernel.org/project/linux-dmaengine/list/ F: drivers/dma/ioat* -INTEL IADX DRIVER +INTEL IDXD DRIVER +M: Fenghua Yu M: Dave Jiang L: dmaengine@vger.kernel.org S: Supported -- cgit v1.2.3 From f7a03501b090f8c5f9ecb08420cda0b168667004 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Mon, 13 Jun 2022 01:23:58 +0300 Subject: dmaengine: stm32-mdma: Remove dead code in stm32_mdma_irq_handler() Local variable chan is initialized by an address of element of chan array that is part of stm32_mdma_device struct, so it does not make sense to compare chan with NULL. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Alexey Khoroshilov Fixes: a4ffb13c8946 ("dmaengine: Add STM32 MDMA driver") Reviewed-by: Amelie Delaunay Link: https://lore.kernel.org/r/1655072638-9103-1-git-send-email-khoroshilov@ispras.ru Signed-off-by: Vinod Koul --- drivers/dma/stm32-mdma.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index caf0cce8f528..b11927ed4367 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -1328,12 +1328,7 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) return IRQ_NONE; } id = __ffs(status); - chan = &dmadev->chan[id]; - if (!chan) { - dev_warn(mdma2dev(dmadev), "MDMA channel not initialized\n"); - return IRQ_NONE; - } /* Handle interrupt for the channel */ spin_lock(&chan->vchan.lock); -- cgit v1.2.3 From 0cae04373b77a117830e5f7d7aaa7eaf01f950d5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 6 Jun 2022 09:47:33 +0200 Subject: dmaengine: remove DMA_MEMCPY_SG once again This was removed before due to the complete lack of users, but 3218910fd585 ("dmaengine: Add core function and capability check for DMA_MEMCPY_SG") and 29cf37fa6dd9 ("dmaengine: Add consumer for the new DMA_MEMCPY_SG API function.") added it back despite still not having any users whatsoever. Fixes: 3218910fd585 ("dmaengine: Add core function and capability check for DMA_MEMCPY_SG") Fixes: 29cf37fa6dd9 ("dmaengine: Add consumer for the new DMA_MEMCPY_SG API function.") Signed-off-by: Christoph Hellwig Acked-by: Michal Simek Link: https://lore.kernel.org/r/20220606074733.622616-1-hch@lst.de Signed-off-by: Vinod Koul --- Documentation/driver-api/dmaengine/provider.rst | 10 -- drivers/dma/dmaengine.c | 7 -- drivers/dma/xilinx/xilinx_dma.c | 122 ------------------------ include/linux/dmaengine.h | 20 ---- 4 files changed, 159 deletions(-) diff --git a/Documentation/driver-api/dmaengine/provider.rst b/Documentation/driver-api/dmaengine/provider.rst index 1e0f1f85d10e..ceac2a300e32 100644 --- a/Documentation/driver-api/dmaengine/provider.rst +++ b/Documentation/driver-api/dmaengine/provider.rst @@ -162,16 +162,6 @@ Currently, the types available are: - The device is able to do memory to memory copies -- - DMA_MEMCPY_SG - - - The device supports memory to memory scatter-gather transfers. - - - Even though a plain memcpy can look like a particular case of a - scatter-gather transfer, with a single chunk to copy, it's a distinct - transaction type in the mem2mem transfer case. This is because some very - simple devices might be able to do contiguous single-chunk memory copies, - but have no support for more complex SG transfers. - - No matter what the overall size of the combined chunks for source and destination is, only as many bytes as the smallest of the two will be transmitted. That means the number and size of the scatter-gather buffers in diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index e80feeea0e01..c741b6431958 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -1153,13 +1153,6 @@ int dma_async_device_register(struct dma_device *device) return -EIO; } - if (dma_has_cap(DMA_MEMCPY_SG, device->cap_mask) && !device->device_prep_dma_memcpy_sg) { - dev_err(device->dev, - "Device claims capability %s, but op is not defined\n", - "DMA_MEMCPY_SG"); - return -EIO; - } - if (dma_has_cap(DMA_XOR, device->cap_mask) && !device->device_prep_dma_xor) { dev_err(device->dev, "Device claims capability %s, but op is not defined\n", diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index cd62bbb50e8b..6276934d4d2b 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -2127,126 +2127,6 @@ error: return NULL; } -/** - * xilinx_cdma_prep_memcpy_sg - prepare descriptors for a memcpy_sg transaction - * @dchan: DMA channel - * @dst_sg: Destination scatter list - * @dst_sg_len: Number of entries in destination scatter list - * @src_sg: Source scatter list - * @src_sg_len: Number of entries in source scatter list - * @flags: transfer ack flags - * - * Return: Async transaction descriptor on success and NULL on failure - */ -static struct dma_async_tx_descriptor *xilinx_cdma_prep_memcpy_sg( - struct dma_chan *dchan, struct scatterlist *dst_sg, - unsigned int dst_sg_len, struct scatterlist *src_sg, - unsigned int src_sg_len, unsigned long flags) -{ - struct xilinx_dma_chan *chan = to_xilinx_chan(dchan); - struct xilinx_dma_tx_descriptor *desc; - struct xilinx_cdma_tx_segment *segment, *prev = NULL; - struct xilinx_cdma_desc_hw *hw; - size_t len, dst_avail, src_avail; - dma_addr_t dma_dst, dma_src; - - if (unlikely(dst_sg_len == 0 || src_sg_len == 0)) - return NULL; - - if (unlikely(!dst_sg || !src_sg)) - return NULL; - - desc = xilinx_dma_alloc_tx_descriptor(chan); - if (!desc) - return NULL; - - dma_async_tx_descriptor_init(&desc->async_tx, &chan->common); - desc->async_tx.tx_submit = xilinx_dma_tx_submit; - - dst_avail = sg_dma_len(dst_sg); - src_avail = sg_dma_len(src_sg); - /* - * loop until there is either no more source or no more destination - * scatterlist entry - */ - while (true) { - len = min_t(size_t, src_avail, dst_avail); - len = min_t(size_t, len, chan->xdev->max_buffer_len); - if (len == 0) - goto fetch; - - /* Allocate the link descriptor from DMA pool */ - segment = xilinx_cdma_alloc_tx_segment(chan); - if (!segment) - goto error; - - dma_dst = sg_dma_address(dst_sg) + sg_dma_len(dst_sg) - - dst_avail; - dma_src = sg_dma_address(src_sg) + sg_dma_len(src_sg) - - src_avail; - hw = &segment->hw; - hw->control = len; - hw->src_addr = dma_src; - hw->dest_addr = dma_dst; - if (chan->ext_addr) { - hw->src_addr_msb = upper_32_bits(dma_src); - hw->dest_addr_msb = upper_32_bits(dma_dst); - } - - if (prev) { - prev->hw.next_desc = segment->phys; - if (chan->ext_addr) - prev->hw.next_desc_msb = - upper_32_bits(segment->phys); - } - - prev = segment; - dst_avail -= len; - src_avail -= len; - list_add_tail(&segment->node, &desc->segments); - -fetch: - /* Fetch the next dst scatterlist entry */ - if (dst_avail == 0) { - if (dst_sg_len == 0) - break; - dst_sg = sg_next(dst_sg); - if (dst_sg == NULL) - break; - dst_sg_len--; - dst_avail = sg_dma_len(dst_sg); - } - /* Fetch the next src scatterlist entry */ - if (src_avail == 0) { - if (src_sg_len == 0) - break; - src_sg = sg_next(src_sg); - if (src_sg == NULL) - break; - src_sg_len--; - src_avail = sg_dma_len(src_sg); - } - } - - if (list_empty(&desc->segments)) { - dev_err(chan->xdev->dev, - "%s: Zero-size SG transfer requested\n", __func__); - goto error; - } - - /* Link the last hardware descriptor with the first. */ - segment = list_first_entry(&desc->segments, - struct xilinx_cdma_tx_segment, node); - desc->async_tx.phys = segment->phys; - prev->hw.next_desc = segment->phys; - - return &desc->async_tx; - -error: - xilinx_dma_free_tx_descriptor(chan, desc); - return NULL; -} - /** * xilinx_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction * @dchan: DMA channel @@ -3240,9 +3120,7 @@ static int xilinx_dma_probe(struct platform_device *pdev) DMA_RESIDUE_GRANULARITY_SEGMENT; } else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) { dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask); - dma_cap_set(DMA_MEMCPY_SG, xdev->common.cap_mask); xdev->common.device_prep_dma_memcpy = xilinx_cdma_prep_memcpy; - xdev->common.device_prep_dma_memcpy_sg = xilinx_cdma_prep_memcpy_sg; /* Residue calculation is supported by only AXI DMA and CDMA */ xdev->common.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index b46b88e6aa0d..c923f4e60f24 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -50,7 +50,6 @@ enum dma_status { */ enum dma_transaction_type { DMA_MEMCPY, - DMA_MEMCPY_SG, DMA_XOR, DMA_PQ, DMA_XOR_VAL, @@ -887,11 +886,6 @@ struct dma_device { struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)( struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, size_t len, unsigned long flags); - struct dma_async_tx_descriptor *(*device_prep_dma_memcpy_sg)( - struct dma_chan *chan, - struct scatterlist *dst_sg, unsigned int dst_nents, - struct scatterlist *src_sg, unsigned int src_nents, - unsigned long flags); struct dma_async_tx_descriptor *(*device_prep_dma_xor)( struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src, unsigned int src_cnt, size_t len, unsigned long flags); @@ -1060,20 +1054,6 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memcpy( len, flags); } -static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memcpy_sg( - struct dma_chan *chan, - struct scatterlist *dst_sg, unsigned int dst_nents, - struct scatterlist *src_sg, unsigned int src_nents, - unsigned long flags) -{ - if (!chan || !chan->device || !chan->device->device_prep_dma_memcpy_sg) - return NULL; - - return chan->device->device_prep_dma_memcpy_sg(chan, dst_sg, dst_nents, - src_sg, src_nents, - flags); -} - static inline bool dmaengine_is_metadata_mode_supported(struct dma_chan *chan, enum dma_desc_metadata_mode mode) { -- cgit v1.2.3 From 3a4413b77429b56bae725363392b56ea65c790c4 Mon Sep 17 00:00:00 2001 From: Jayesh Choudhary Date: Tue, 28 Jun 2022 10:32:32 +0530 Subject: dmaengine: ti: k3-psil-j721s2: Add psil threads for sa2ul Add endpoint configuration for the four ingress and two egress threads for main domain crypto accelerator. Signed-off-by: Jayesh Choudhary Link: https://lore.kernel.org/r/20220628050232.331956-1-j-choudhary@ti.com Signed-off-by: Vinod Koul --- drivers/dma/ti/k3-psil-j721s2.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/dma/ti/k3-psil-j721s2.c b/drivers/dma/ti/k3-psil-j721s2.c index 4c4172a4d271..a488c2250623 100644 --- a/drivers/dma/ti/k3-psil-j721s2.c +++ b/drivers/dma/ti/k3-psil-j721s2.c @@ -112,6 +112,11 @@ static struct psil_ep j721s2_src_ep_map[] = { PSIL_PDMA_XY_PKT(0x4707), PSIL_PDMA_XY_PKT(0x4708), PSIL_PDMA_XY_PKT(0x4709), + /* MAIN SA2UL */ + PSIL_SA2UL(0x4a40, 0), + PSIL_SA2UL(0x4a41, 0), + PSIL_SA2UL(0x4a42, 0), + PSIL_SA2UL(0x4a43, 0), /* CPSW0 */ PSIL_ETHERNET(0x7000), /* MCU_PDMA0 (MCU_PDMA_MISC_G0) - SPI0 */ @@ -144,6 +149,9 @@ static struct psil_ep j721s2_src_ep_map[] = { /* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */ static struct psil_ep j721s2_dst_ep_map[] = { + /* MAIN SA2UL */ + PSIL_SA2UL(0xca40, 1), + PSIL_SA2UL(0xca41, 1), /* CPSW0 */ PSIL_ETHERNET(0xf000), PSIL_ETHERNET(0xf001), -- cgit v1.2.3 From 0951a90e343d20b62daa7720da61f124b1c32d71 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 23 Jun 2022 09:33:53 -0300 Subject: dmaengine: imx-sdma: Improve the SDMA irq name On SoCs with several SDMA instances, such as i.MX8M for example, all the SDMA related interrupts appear with the same "sdma" name. Improve the SDMA irq name by associating it with the SDMA instance via dev_name(), so that the SDMA irq names can be unique. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20220623123353.2570410-1-festevam@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/imx-sdma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 8535018ee7a2..43d78e98a912 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -2183,8 +2183,8 @@ static int sdma_probe(struct platform_device *pdev) if (ret) goto err_clk; - ret = devm_request_irq(&pdev->dev, irq, sdma_int_handler, 0, "sdma", - sdma); + ret = devm_request_irq(&pdev->dev, irq, sdma_int_handler, 0, + dev_name(&pdev->dev), sdma); if (ret) goto err_irq; -- cgit v1.2.3 From a7a5c1a93d83e5b6331d6ed94f1bcdb15cc9a6c0 Mon Sep 17 00:00:00 2001 From: Jiang Jian Date: Wed, 22 Jun 2022 22:31:58 +0800 Subject: dmaengine: ep93xx: Fix typo in comments Remove the repeated word 'and' from comments Signed-off-by: Jiang Jian Link: https://lore.kernel.org/r/20220622143158.15091-1-jiangjian@cdjrlc.com Signed-off-by: Vinod Koul --- drivers/dma/ep93xx_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index 971ff5f9ae84..d19ea885c63e 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -1183,7 +1183,7 @@ fail: * * Synchronizes the DMA channel termination to the current context. When this * function returns it is guaranteed that all transfers for previously issued - * descriptors have stopped and and it is safe to free the memory associated + * descriptors have stopped and it is safe to free the memory associated * with them. Furthermore it is guaranteed that all complete callback functions * for a previously submitted descriptor have finished running and it is safe to * free resources accessed from within the complete callbacks. -- cgit v1.2.3 From cfa1927f8468c76e42d727693a3c2be1a9540ee1 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 20 Jun 2022 10:00:02 +0800 Subject: dt-bindings: dma: fsl-edma: Convert to DT schema Convert the eDMA controller binding to DT schema. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20220620020002.3966343-1-peng.fan@oss.nxp.com Signed-off-by: Vinod Koul --- .../devicetree/bindings/dma/fsl,edma.yaml | 155 +++++++++++++++++++++ Documentation/devicetree/bindings/dma/fsl-edma.txt | 111 --------------- 2 files changed, 155 insertions(+), 111 deletions(-) create mode 100644 Documentation/devicetree/bindings/dma/fsl,edma.yaml delete mode 100644 Documentation/devicetree/bindings/dma/fsl-edma.txt diff --git a/Documentation/devicetree/bindings/dma/fsl,edma.yaml b/Documentation/devicetree/bindings/dma/fsl,edma.yaml new file mode 100644 index 000000000000..050e6cd57727 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/fsl,edma.yaml @@ -0,0 +1,155 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/fsl,edma.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale enhanced Direct Memory Access(eDMA) Controller + +description: | + The eDMA channels have multiplex capability by programmable + memory-mapped registers. channels are split into two groups, called + DMAMUX0 and DMAMUX1, specific DMA request source can only be multiplexed + by any channel of certain group, DMAMUX0 or DMAMUX1, but not both. + +maintainers: + - Peng Fan + +properties: + compatible: + oneOf: + - enum: + - fsl,vf610-edma + - fsl,imx7ulp-edma + - items: + - const: fsl,ls1028a-edma + - const: fsl,vf610-edma + + reg: + minItems: 2 + maxItems: 3 + + interrupts: + minItems: 2 + maxItems: 17 + + interrupt-names: + minItems: 2 + maxItems: 17 + + "#dma-cells": + const: 2 + + dma-channels: + const: 32 + + clocks: + maxItems: 2 + + clock-names: + maxItems: 2 + + big-endian: + description: | + If present registers and hardware scatter/gather descriptors of the + eDMA are implemented in big endian mode, otherwise in little mode. + type: boolean + +required: + - "#dma-cells" + - compatible + - reg + - interrupts + - clocks + - dma-channels + +allOf: + - $ref: "dma-controller.yaml#" + - if: + properties: + compatible: + contains: + const: fsl,vf610-edma + then: + properties: + clock-names: + items: + - const: dmamux0 + - const: dmamux1 + interrupts: + maxItems: 2 + interrupt-names: + items: + - const: edma-tx + - const: edma-err + reg: + maxItems: 3 + + - if: + properties: + compatible: + contains: + const: fsl,imx7ulp-edma + then: + properties: + clock-names: + items: + - const: dma + - const: dmamux0 + interrupts: + maxItems: 17 + reg: + maxItems: 2 + +unevaluatedProperties: false + +examples: + - | + #include + #include + + edma0: dma-controller@40018000 { + #dma-cells = <2>; + compatible = "fsl,vf610-edma"; + reg = <0x40018000 0x2000>, + <0x40024000 0x1000>, + <0x40025000 0x1000>; + interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>, + <0 9 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "edma-tx", "edma-err"; + dma-channels = <32>; + clock-names = "dmamux0", "dmamux1"; + clocks = <&clks VF610_CLK_DMAMUX0>, <&clks VF610_CLK_DMAMUX1>; + }; + + - | + #include + #include + + edma1: dma-controller@40080000 { + #dma-cells = <2>; + compatible = "fsl,imx7ulp-edma"; + reg = <0x40080000 0x2000>, + <0x40210000 0x1000>; + dma-channels = <32>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + /* last is eDMA2-ERR interrupt */ + ; + clock-names = "dma", "dmamux0"; + clocks = <&pcc2 IMX7ULP_CLK_DMA1>, <&pcc2 IMX7ULP_CLK_DMA_MUX1>; + }; diff --git a/Documentation/devicetree/bindings/dma/fsl-edma.txt b/Documentation/devicetree/bindings/dma/fsl-edma.txt deleted file mode 100644 index ee1754739b4b..000000000000 --- a/Documentation/devicetree/bindings/dma/fsl-edma.txt +++ /dev/null @@ -1,111 +0,0 @@ -* Freescale enhanced Direct Memory Access(eDMA) Controller - - The eDMA channels have multiplex capability by programmble memory-mapped -registers. channels are split into two groups, called DMAMUX0 and DMAMUX1, -specific DMA request source can only be multiplexed by any channel of certain -group, DMAMUX0 or DMAMUX1, but not both. - -* eDMA Controller -Required properties: -- compatible : - - "fsl,vf610-edma" for eDMA used similar to that on Vybrid vf610 SoC - - "fsl,imx7ulp-edma" for eDMA2 used similar to that on i.mx7ulp - - "fsl,ls1028a-edma" followed by "fsl,vf610-edma" for eDMA used on the - LS1028A SoC. -- reg : Specifies base physical address(s) and size of the eDMA registers. - The 1st region is eDMA control register's address and size. - The 2nd and the 3rd regions are programmable channel multiplexing - control register's address and size. -- interrupts : A list of interrupt-specifiers, one for each entry in - interrupt-names on vf610 similar SoC. But for i.mx7ulp per channel - per transmission interrupt, total 16 channel interrupt and 1 - error interrupt(located in the last), no interrupt-names list on - i.mx7ulp for clean on dts. -- #dma-cells : Must be <2>. - The 1st cell specifies the DMAMUX(0 for DMAMUX0 and 1 for DMAMUX1). - Specific request source can only be multiplexed by specific channels - group called DMAMUX. - The 2nd cell specifies the request source(slot) ID. - See the SoC's reference manual for all the supported request sources. -- dma-channels : Number of channels supported by the controller -- clock-names : A list of channel group clock names. Should contain: - "dmamux0" - clock name of mux0 group - "dmamux1" - clock name of mux1 group - Note: No dmamux0 on i.mx7ulp, but another 'dma' clk added on i.mx7ulp. -- clocks : A list of phandle and clock-specifier pairs, one for each entry in - clock-names. - -Optional properties: -- big-endian: If present registers and hardware scatter/gather descriptors - of the eDMA are implemented in big endian mode, otherwise in little - mode. -- interrupt-names : Should contain the below on vf610 similar SoC but not used - on i.mx7ulp similar SoC: - "edma-tx" - the transmission interrupt - "edma-err" - the error interrupt - - -Examples: - -edma0: dma-controller@40018000 { - #dma-cells = <2>; - compatible = "fsl,vf610-edma"; - reg = <0x40018000 0x2000>, - <0x40024000 0x1000>, - <0x40025000 0x1000>; - interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>, - <0 9 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "edma-tx", "edma-err"; - dma-channels = <32>; - clock-names = "dmamux0", "dmamux1"; - clocks = <&clks VF610_CLK_DMAMUX0>, - <&clks VF610_CLK_DMAMUX1>; -}; /* vf610 */ - -edma1: dma-controller@40080000 { - #dma-cells = <2>; - compatible = "fsl,imx7ulp-edma"; - reg = <0x40080000 0x2000>, - <0x40210000 0x1000>; - dma-channels = <32>; - interrupts = , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - /* last is eDMA2-ERR interrupt */ - ; - clock-names = "dma", "dmamux0"; - clocks = <&pcc2 IMX7ULP_CLK_DMA1>, - <&pcc2 IMX7ULP_CLK_DMA_MUX1>; -}; /* i.mx7ulp */ - -* DMA clients -DMA client drivers that uses the DMA function must use the format described -in the dma.txt file, using a two-cell specifier for each channel: the 1st -specifies the channel group(DMAMUX) in which this request can be multiplexed, -and the 2nd specifies the request source. - -Examples: - -sai2: sai@40031000 { - compatible = "fsl,vf610-sai"; - reg = <0x40031000 0x1000>; - interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>; - clock-names = "sai"; - clocks = <&clks VF610_CLK_SAI2>; - dma-names = "tx", "rx"; - dmas = <&edma0 0 21>, - <&edma0 0 20>; -}; -- cgit v1.2.3 From ab356484dbb950b069b363e45681270eb14fd02c Mon Sep 17 00:00:00 2001 From: Xiang wangx Date: Sat, 18 Jun 2022 21:03:49 +0800 Subject: dmaengine: at_xdmac: Fix typo in comment Delete the redundant word 'the'. Signed-off-by: Xiang wangx Link: https://lore.kernel.org/r/20220618130349.11507-1-wangxiang@cdjrlc.com Signed-off-by: Vinod Koul --- drivers/dma/at_xdmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index 3e9d726504e2..90cbff44f884 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -649,7 +649,7 @@ static int at_xdmac_compute_chan_conf(struct dma_chan *chan, } /* - * Only check that maxburst and addr width values are supported by the + * Only check that maxburst and addr width values are supported by * the controller but not that the configuration is good to perform the * transfer since we don't know the direction at this stage. */ -- cgit v1.2.3 From 8d8bbefa6a3397e6f730dd75ba5128d9d106d4ea Mon Sep 17 00:00:00 2001 From: Xiang wangx Date: Sat, 18 Jun 2022 21:01:20 +0800 Subject: dmaengine: mediatek: mtk-hsdma: Fix typo in comment Delete the redundant word 'be'. Signed-off-by: Xiang wangx Link: https://lore.kernel.org/r/20220618130120.9783-1-wangxiang@cdjrlc.com Signed-off-by: Vinod Koul --- drivers/dma/mediatek/mtk-hsdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c index 9ebd9231f62f..a72e5a096c5c 100644 --- a/drivers/dma/mediatek/mtk-hsdma.c +++ b/drivers/dma/mediatek/mtk-hsdma.c @@ -761,7 +761,7 @@ static void mtk_hsdma_free_active_desc(struct dma_chan *c) /* * Once issue_synchronize is being set, which means once the hardware * consumes all descriptors for the channel in the ring, the - * synchronization must be be notified immediately it is completed. + * synchronization must be notified immediately it is completed. */ spin_lock(&hvc->vc.lock); if (!list_empty(&hvc->desc_hw_processing)) { -- cgit v1.2.3 From 9bef4929fa21477d44b4934d02296c4d0126dd40 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 14 Jun 2022 19:47:59 +0100 Subject: dmaengine: fsl-edma: remove redundant assignment to pointer last_sg The pointer last_sg is being assigned a value at the start of a loop however it is never read and is being re-assigned later on in both brances of an if-statement. The assignment is redundant and can be removed. Cleans up clang scan-build warning: drivers/dma/fsl-edma-common.c:563:3: warning: Value stored to 'last_sg' is never read [deadcode.DeadStores] Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20220614184759.164379-1-colin.i.king@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/fsl-edma-common.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c index 3ae05d1446a5..a06a1575a2a5 100644 --- a/drivers/dma/fsl-edma-common.c +++ b/drivers/dma/fsl-edma-common.c @@ -559,9 +559,6 @@ struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg( } for_each_sg(sgl, sg, sg_len, i) { - /* get next sg's physical address */ - last_sg = fsl_desc->tcd[(i + 1) % sg_len].ptcd; - if (direction == DMA_MEM_TO_DEV) { src_addr = sg_dma_address(sg); dst_addr = fsl_chan->dma_dev_addr; -- cgit v1.2.3 From a94a098a21c678c07c8a742e4a65e8aa2bebdf08 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 20 Jun 2022 22:13:50 -0500 Subject: dmaengine: sun4i: Set the maximum segment size The sun4i DMA engine supports transfer sizes up to 128k for normal DMA and 16M for dedicated DMA, as documented in the A10 and A20 manuals. Since this is larger than the default segment size limit (64k), exposing the real limit reduces the number of transfers needed for a transaction. However, because the device can only report one segment size limit, we have to expose the smaller limit from normal DMA. One complication is that the driver combines pairs of periodic transfers to reduce programming overhead. This only works when the period size is at most half of the maximum transfer size. With the default 64k segment size limit, this was always the case, but for normal DMA it is no longer guaranteed. Skip the optimization if the period is too long; even without it, the overhead is less than before. Signed-off-by: Samuel Holland Link: https://lore.kernel.org/r/20220621031350.36187-1-samuel@sholland.org Signed-off-by: Vinod Koul --- drivers/dma/sun4i-dma.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c index 93f1645ae928..f291b1b4db32 100644 --- a/drivers/dma/sun4i-dma.c +++ b/drivers/dma/sun4i-dma.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -122,6 +123,15 @@ SUN4I_DDMA_PARA_DST_WAIT_CYCLES(2) | \ SUN4I_DDMA_PARA_SRC_WAIT_CYCLES(2)) +/* + * Normal DMA supports individual transfers (segments) up to 128k. + * Dedicated DMA supports transfers up to 16M. We can only report + * one size limit, so we have to use the smaller value. + */ +#define SUN4I_NDMA_MAX_SEG_SIZE SZ_128K +#define SUN4I_DDMA_MAX_SEG_SIZE SZ_16M +#define SUN4I_DMA_MAX_SEG_SIZE SUN4I_NDMA_MAX_SEG_SIZE + struct sun4i_dma_pchan { /* Register base of channel */ void __iomem *base; @@ -155,7 +165,8 @@ struct sun4i_dma_contract { struct virt_dma_desc vd; struct list_head demands; struct list_head completed_demands; - int is_cyclic; + bool is_cyclic : 1; + bool use_half_int : 1; }; struct sun4i_dma_dev { @@ -372,7 +383,7 @@ static int __execute_vchan_pending(struct sun4i_dma_dev *priv, if (promise) { vchan->contract = contract; vchan->pchan = pchan; - set_pchan_interrupt(priv, pchan, contract->is_cyclic, 1); + set_pchan_interrupt(priv, pchan, contract->use_half_int, 1); configure_pchan(pchan, promise); } @@ -735,12 +746,21 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len, * * Which requires half the engine programming for the same * functionality. + * + * This only works if two periods fit in a single promise. That will + * always be the case for dedicated DMA, where the hardware has a much + * larger maximum transfer size than advertised to clients. */ - nr_periods = DIV_ROUND_UP(len / period_len, 2); + if (vchan->is_dedicated || period_len <= SUN4I_NDMA_MAX_SEG_SIZE / 2) { + period_len *= 2; + contract->use_half_int = 1; + } + + nr_periods = DIV_ROUND_UP(len, period_len); for (i = 0; i < nr_periods; i++) { /* Calculate the offset in the buffer and the length needed */ - offset = i * period_len * 2; - plength = min((len - offset), (period_len * 2)); + offset = i * period_len; + plength = min((len - offset), period_len); if (dir == DMA_MEM_TO_DEV) src = buf + offset; else @@ -1149,6 +1169,8 @@ static int sun4i_dma_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); spin_lock_init(&priv->lock); + dma_set_max_seg_size(&pdev->dev, SUN4I_DMA_MAX_SEG_SIZE); + dma_cap_zero(priv->slave.cap_mask); dma_cap_set(DMA_PRIVATE, priv->slave.cap_mask); dma_cap_set(DMA_MEMCPY, priv->slave.cap_mask); -- cgit v1.2.3 From 8f64c2a4c8b59fe6dfc29add92c55947b1299da3 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Thu, 19 May 2022 21:08:55 +0800 Subject: dmaengine: xilinx_dpdma: Omit superfluous error message in xilinx_dpdma_probe() In the function xilinx_dpdma_probe(), when get irq failed, the function platform_get_irq() logs an error message, so remove redundant message here. Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20220519130855.7664-1-tangbin@cmss.chinamobile.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_dpdma.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c index b0f4948b00a5..f708808d73ba 100644 --- a/drivers/dma/xilinx/xilinx_dpdma.c +++ b/drivers/dma/xilinx/xilinx_dpdma.c @@ -1652,10 +1652,8 @@ static int xilinx_dpdma_probe(struct platform_device *pdev) dpdma_hw_init(xdev); xdev->irq = platform_get_irq(pdev, 0); - if (xdev->irq < 0) { - dev_err(xdev->dev, "failed to get platform irq\n"); + if (xdev->irq < 0) return xdev->irq; - } ret = request_irq(xdev->irq, xilinx_dpdma_irq_handler, IRQF_SHARED, dev_name(xdev->dev), xdev); -- cgit v1.2.3 From e4c4182f3c55648d427060da55ad6aa55269651a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:11:01 +0200 Subject: dmaengine: fix typos in comments Spelling mistakes (triple letters) in comments. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20220521111145.81697-51-Julia.Lawall@inria.fr Signed-off-by: Vinod Koul --- drivers/dma/amba-pl08x.c | 2 +- drivers/dma/mv_xor_v2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index a4a794e62ac2..487a01aa207d 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -231,7 +231,7 @@ enum pl08x_dma_chan_state { /** * struct pl08x_dma_chan - this structure wraps a DMA ENGINE channel - * @vc: wrappped virtual channel + * @vc: wrapped virtual channel * @phychan: the physical channel utilized by this channel, if there is one * @name: name of channel * @cd: channel platform data diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index f10b29034da1..f629ef6fd3c2 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -313,7 +313,7 @@ mv_xor_v2_tx_submit(struct dma_async_tx_descriptor *tx) "%s sw_desc %p: async_tx %p\n", __func__, sw_desc, &sw_desc->async_tx); - /* assign coookie */ + /* assign cookie */ spin_lock_bh(&xor_dev->lock); cookie = dma_cookie_assign(tx); -- cgit v1.2.3 From fd39ae75b66260f235b05e48246fe63e9ea1a0e5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:11:11 +0200 Subject: dmaengine: mediatek-cqdma: fix typo in comment Spelling mistake (triple letters) in comment. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20220521111145.81697-61-Julia.Lawall@inria.fr Signed-off-by: Vinod Koul --- drivers/dma/mediatek/mtk-cqdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/mediatek/mtk-cqdma.c b/drivers/dma/mediatek/mtk-cqdma.c index f8847c48ba03..9ae92b8940ef 100644 --- a/drivers/dma/mediatek/mtk-cqdma.c +++ b/drivers/dma/mediatek/mtk-cqdma.c @@ -373,7 +373,7 @@ static void mtk_cqdma_tasklet_cb(struct tasklet_struct *t) /* * free child CVD after completion. - * the parent CVD would be freeed with desc_free by user. + * the parent CVD would be freed with desc_free by user. */ if (cvd->parent != cvd) kfree(cvd); -- cgit v1.2.3 From 2749416f7529993afc8dedaf7e3ce5e5114d40c1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:10:17 +0200 Subject: dmaengine: owl: fix typo in comment Spelling mistake (triple letters) in comment. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20220521111145.81697-7-Julia.Lawall@inria.fr Signed-off-by: Vinod Koul --- drivers/dma/owl-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c index 1f0bbaed4643..95a462a1f511 100644 --- a/drivers/dma/owl-dma.c +++ b/drivers/dma/owl-dma.c @@ -193,7 +193,7 @@ struct owl_dma_pchan { /** * struct owl_dma_pchan - Wrapper for DMA ENGINE channel - * @vc: wrappped virtual channel + * @vc: wrapped virtual channel * @pchan: the physical channel utilized by this channel * @txd: active transaction on this channel * @cfg: slave configuration for this channel -- cgit v1.2.3 From 6a4e9307cd3782f8e805fac970b9a240ab3078d6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:11:12 +0200 Subject: dmaengine: qcom: fix typo in comment Spelling mistake (triple letters) in comment. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20220521111145.81697-62-Julia.Lawall@inria.fr Signed-off-by: Vinod Koul --- include/linux/dma/qcom-gpi-dma.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/dma/qcom-gpi-dma.h b/include/linux/dma/qcom-gpi-dma.h index f46dc3372f11..6680dd1a43c6 100644 --- a/include/linux/dma/qcom-gpi-dma.h +++ b/include/linux/dma/qcom-gpi-dma.h @@ -26,7 +26,7 @@ enum spi_transfer_cmd { * @clk_div: source clock divider * @clk_src: serial clock * @cmd: spi cmd - * @fragmentation: keep CS assserted at end of sequence + * @fragmentation: keep CS asserted at end of sequence * @cs: chip select toggle * @set_config: set peripheral config * @rx_len: receive length for buffer -- cgit v1.2.3 From a0e02b8cfb0559dbaf0e1a79e4944d5ad0d914f2 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:10:56 +0200 Subject: dmaengine: s3c24xx: fix typo in comment Spelling mistake (triple letters) in comment. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220521111145.81697-46-Julia.Lawall@inria.fr Signed-off-by: Vinod Koul --- drivers/dma/s3c24xx-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c index 8e14c72d03f0..f6ed7e889781 100644 --- a/drivers/dma/s3c24xx-dma.c +++ b/drivers/dma/s3c24xx-dma.c @@ -202,7 +202,7 @@ struct s3c24xx_dma_phy { * struct s3c24xx_dma_chan - this structure wraps a DMA ENGINE channel * @id: the id of the channel * @name: name of the channel - * @vc: wrappped virtual channel + * @vc: wrapped virtual channel * @phy: the physical channel utilized by this channel, if there is one * @runtime_addr: address for RX/TX according to the runtime config * @at: active transaction on this channel -- cgit v1.2.3 From 0d7c11af47aa3b065dc0bbc96d42baf411ce09e0 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:10:30 +0200 Subject: dmaengine: jz4780: fix typo in comment Spelling mistake (triple letters) in comment. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Acked-by: Paul Cercueil Link: https://lore.kernel.org/r/20220521111145.81697-20-Julia.Lawall@inria.fr Signed-off-by: Vinod Koul --- drivers/dma/dma-jz4780.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c index e2ec540e6519..2a483802d9ee 100644 --- a/drivers/dma/dma-jz4780.c +++ b/drivers/dma/dma-jz4780.c @@ -388,7 +388,7 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg( if (i != (sg_len - 1) && !(jzdma->soc_data->flags & JZ_SOC_DATA_BREAK_LINKS)) { - /* Automatically proceeed to the next descriptor. */ + /* Automatically proceed to the next descriptor. */ desc->desc[i].dcm |= JZ_DMA_DCM_LINK; /* -- cgit v1.2.3 From a71da24ce1f8f6844c6378ae394b5c4b31ff5725 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:10:27 +0200 Subject: dmaengine: ste_dma40: fix typo in comment Spelling mistake (triple letters) in comment. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20220521111145.81697-17-Julia.Lawall@inria.fr Signed-off-by: Vinod Koul --- drivers/dma/ste_dma40.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index e1827393143f..f093e08c23b1 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -1970,7 +1970,7 @@ static int d40_config_memcpy(struct d40_chan *d40c) dma_has_cap(DMA_SLAVE, cap)) { d40c->dma_cfg = dma40_memcpy_conf_phy; - /* Generate interrrupt at end of transfer or relink. */ + /* Generate interrupt at end of transfer or relink. */ d40c->dst_def_cfg |= BIT(D40_SREG_CFG_TIM_POS); /* Generate interrupt on error. */ -- cgit v1.2.3 From 6bc7ea3c9b49c869f688d949bb473c4e1484894f Mon Sep 17 00:00:00 2001 From: XueBing Chen Date: Wed, 25 May 2022 17:03:03 +0800 Subject: dmaengine: dmatest: use strscpy to replace strlcpy The strlcpy should not be used because it doesn't limit the source length. Preferred is strscpy. Signed-off-by: XueBing Chen Link: https://lore.kernel.org/r/12e4cf06.a35.180fa748c29.Coremail.chenxuebing@jari.cn Signed-off-by: Vinod Koul --- drivers/dma/dmatest.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 3253d1da2b3a..5c84841de21a 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -1101,8 +1101,8 @@ static void add_threaded_test(struct dmatest_info *info) /* Copy test parameters */ params->buf_size = test_buf_size; - strlcpy(params->channel, strim(test_channel), sizeof(params->channel)); - strlcpy(params->device, strim(test_device), sizeof(params->device)); + strscpy(params->channel, strim(test_channel), sizeof(params->channel)); + strscpy(params->device, strim(test_device), sizeof(params->device)); params->threads_per_chan = threads_per_chan; params->max_channels = max_channels; params->iterations = iterations; @@ -1246,7 +1246,7 @@ static int dmatest_chan_set(const char *val, const struct kernel_param *kp) dtc = list_last_entry(&info->channels, struct dmatest_chan, node); - strlcpy(chan_reset_val, + strscpy(chan_reset_val, dma_chan_name(dtc->chan), sizeof(chan_reset_val)); ret = -EBUSY; @@ -1269,14 +1269,14 @@ static int dmatest_chan_set(const char *val, const struct kernel_param *kp) if ((strcmp(dma_chan_name(dtc->chan), strim(test_channel)) != 0) && (strcmp("", strim(test_channel)) != 0)) { ret = -EINVAL; - strlcpy(chan_reset_val, dma_chan_name(dtc->chan), + strscpy(chan_reset_val, dma_chan_name(dtc->chan), sizeof(chan_reset_val)); goto add_chan_err; } } else { /* Clear test_channel if no channels were added successfully */ - strlcpy(chan_reset_val, "", sizeof(chan_reset_val)); + strscpy(chan_reset_val, "", sizeof(chan_reset_val)); ret = -EBUSY; goto add_chan_err; } @@ -1301,7 +1301,7 @@ static int dmatest_chan_get(char *val, const struct kernel_param *kp) mutex_lock(&info->lock); if (!is_threaded_test_run(info) && !is_threaded_test_pending(info)) { stop_threaded_test(info); - strlcpy(test_channel, "", sizeof(test_channel)); + strscpy(test_channel, "", sizeof(test_channel)); } mutex_unlock(&info->lock); -- cgit v1.2.3 From 4ce653d7c651d6a9fc6d5db4275624ac8d856b99 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Tue, 5 Jul 2022 22:52:04 +0100 Subject: dt-bindings: dma: dw-axi-dmac: extend the number of interrupts The Canaan k210 apparently has a Sysnopsys Designware AXI DMA controller, but according to the documentation & devicetree it has 6 interrupts rather than the standard one. Support the 6 interrupt configuration by unconditionally extending the binding to a maximum of 8 per-channel interrupts thereby matching the number of possible channels. Link: https://canaan-creative.com/wp-content/uploads/2020/03/kendryte_standalone_programming_guide_20190311144158_en.pdf #Page 51 Reviewed-by: Serge Semin Reviewed-by: Rob Herring Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20220705215213.1802496-4-mail@conchuod.ie Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml b/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml index 4324a94b26b2..67aa7bb6d36a 100644 --- a/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml +++ b/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml @@ -34,7 +34,12 @@ properties: - const: axidma_apb_regs interrupts: - maxItems: 1 + description: + If the IP-core synthesis parameter DMAX_INTR_IO_TYPE is set to 1, this + will be per-channel interrupts. Otherwise, this is a single combined IRQ + for all channels. + minItems: 1 + maxItems: 8 clocks: items: -- cgit v1.2.3 From b2cc5c465c2cb8ab697c3fd6583c614e3f6cfbcc Mon Sep 17 00:00:00 2001 From: Viacheslav Mitrofanov Date: Fri, 1 Jul 2022 11:29:42 +0300 Subject: dmaengine: sf-pdma: Add multithread support for a DMA channel When we get a DMA channel and try to use it in multiple threads it will cause oops and hanging the system. % echo 64 > /sys/module/dmatest/parameters/threads_per_chan % echo 10000 > /sys/module/dmatest/parameters/iterations % echo 1 > /sys/module/dmatest/parameters/run [ 89.480664] Unable to handle kernel NULL pointer dereference at virtual address 00000000000000a0 [ 89.488725] Oops [#1] [ 89.494708] CPU: 2 PID: 1008 Comm: dma0chan0-copy0 Not tainted 5.17.0-rc5 [ 89.509385] epc : vchan_find_desc+0x32/0x46 [ 89.513553] ra : sf_pdma_tx_status+0xca/0xd6 This happens because of data race. Each thread rewrite channels's descriptor as soon as device_prep_dma_memcpy() is called. It leads to the situation when the driver thinks that it uses right descriptor that actually is freed or substituted for other one. With current fixes a descriptor changes its value only when it has been used. A new descriptor is acquired from vc->desc_issued queue that is already filled with descriptors that are ready to be sent. Threads have no direct access to DMA channel descriptor. Now it is just possible to queue a descriptor for further processing. Fixes: 6973886ad58e ("dmaengine: sf-pdma: add platform DMA support for HiFive Unleashed A00") Signed-off-by: Viacheslav Mitrofanov Link: https://lore.kernel.org/r/20220701082942.12835-1-v.v.mitrofanov@yadro.com Signed-off-by: Vinod Koul --- drivers/dma/sf-pdma/sf-pdma.c | 44 +++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/drivers/dma/sf-pdma/sf-pdma.c b/drivers/dma/sf-pdma/sf-pdma.c index db5a4ef76077..4f8b8498c5c6 100644 --- a/drivers/dma/sf-pdma/sf-pdma.c +++ b/drivers/dma/sf-pdma/sf-pdma.c @@ -52,16 +52,6 @@ static inline struct sf_pdma_desc *to_sf_pdma_desc(struct virt_dma_desc *vd) static struct sf_pdma_desc *sf_pdma_alloc_desc(struct sf_pdma_chan *chan) { struct sf_pdma_desc *desc; - unsigned long flags; - - spin_lock_irqsave(&chan->lock, flags); - - if (chan->desc && !chan->desc->in_use) { - spin_unlock_irqrestore(&chan->lock, flags); - return chan->desc; - } - - spin_unlock_irqrestore(&chan->lock, flags); desc = kzalloc(sizeof(*desc), GFP_NOWAIT); if (!desc) @@ -111,7 +101,6 @@ sf_pdma_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dest, dma_addr_t src, desc->async_tx = vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); spin_lock_irqsave(&chan->vchan.lock, iflags); - chan->desc = desc; sf_pdma_fill_desc(desc, dest, src, len); spin_unlock_irqrestore(&chan->vchan.lock, iflags); @@ -170,11 +159,17 @@ static size_t sf_pdma_desc_residue(struct sf_pdma_chan *chan, unsigned long flags; u64 residue = 0; struct sf_pdma_desc *desc; - struct dma_async_tx_descriptor *tx; + struct dma_async_tx_descriptor *tx = NULL; spin_lock_irqsave(&chan->vchan.lock, flags); - tx = &chan->desc->vdesc.tx; + list_for_each_entry(vd, &chan->vchan.desc_submitted, node) + if (vd->tx.cookie == cookie) + tx = &vd->tx; + + if (!tx) + goto out; + if (cookie == tx->chan->completed_cookie) goto out; @@ -241,6 +236,19 @@ static void sf_pdma_enable_request(struct sf_pdma_chan *chan) writel(v, regs->ctrl); } +static struct sf_pdma_desc *sf_pdma_get_first_pending_desc(struct sf_pdma_chan *chan) +{ + struct virt_dma_chan *vchan = &chan->vchan; + struct virt_dma_desc *vdesc; + + if (list_empty(&vchan->desc_issued)) + return NULL; + + vdesc = list_first_entry(&vchan->desc_issued, struct virt_dma_desc, node); + + return container_of(vdesc, struct sf_pdma_desc, vdesc); +} + static void sf_pdma_xfer_desc(struct sf_pdma_chan *chan) { struct sf_pdma_desc *desc = chan->desc; @@ -268,8 +276,11 @@ static void sf_pdma_issue_pending(struct dma_chan *dchan) spin_lock_irqsave(&chan->vchan.lock, flags); - if (vchan_issue_pending(&chan->vchan) && chan->desc) + if (!chan->desc && vchan_issue_pending(&chan->vchan)) { + /* vchan_issue_pending has made a check that desc in not NULL */ + chan->desc = sf_pdma_get_first_pending_desc(chan); sf_pdma_xfer_desc(chan); + } spin_unlock_irqrestore(&chan->vchan.lock, flags); } @@ -298,6 +309,11 @@ static void sf_pdma_donebh_tasklet(struct tasklet_struct *t) spin_lock_irqsave(&chan->vchan.lock, flags); list_del(&chan->desc->vdesc.node); vchan_cookie_complete(&chan->desc->vdesc); + + chan->desc = sf_pdma_get_first_pending_desc(chan); + if (chan->desc) + sf_pdma_xfer_desc(chan); + spin_unlock_irqrestore(&chan->vchan.lock, flags); } -- cgit v1.2.3 From 01eafd4b23805890dfe8b3e639f1bf299a6dbcf5 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 6 Jul 2022 13:45:09 +0800 Subject: dmaengine: imx-sdma: Add missing struct documentation Fix compile warning that 'Function parameter or member not described' with 'W=1' option: Add missing description for struct sdma_desc There is not any description for struct sdma_script_start_addrs, so use /* instead of /** Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1657086309-7964-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Vinod Koul --- drivers/dma/imx-sdma.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 43d78e98a912..8a5d4d4a4dff 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -188,7 +188,7 @@ #define SDMA_DONE0_CONFIG_DONE_SEL BIT(7) #define SDMA_DONE0_CONFIG_DONE_DIS BIT(6) -/** +/* * struct sdma_script_start_addrs - SDMA script start pointers * * start addresses of the different functions in the physical @@ -424,6 +424,11 @@ struct sdma_desc { * @data: specific sdma interface structure * @bd_pool: dma_pool for bd * @terminate_worker: used to call back into terminate work function + * @terminated: terminated list + * @is_ram_script: flag for script in ram + * @n_fifos_src: number of source device fifos + * @n_fifos_dst: number of destination device fifos + * @sw_done: software done flag */ struct sdma_channel { struct virt_dma_chan vc; -- cgit v1.2.3 From 4348d99efa01fe030eb625495de8b9f3578b5c7d Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Wed, 6 Jul 2022 16:26:05 +0800 Subject: dmaengine: altera-msgdma: Fixed some inconsistent function name descriptions Inconsistent function names describing msgdma_chan_remove() and msgdma_dma_remove are modified to msgdma_dev_remove() and msgdma_remove(). Remove some warnings found by running scripts/kernel-doc, which is caused by using 'make W=1'. drivers/dma/altera-msgdma.c:927: warning: expecting prototype for msgdma_dma_remove(). Prototype was for msgdma_remove() instead. drivers/dma/altera-msgdma.c:758: warning: expecting prototype for msgdma_chan_remove(). Prototype was for msgdma_dev_remove() instead. Signed-off-by: Jiapeng Chong Reviewed-by: Stefan Roese Link: https://lore.kernel.org/r/20220706082605.114907-1-jiapeng.chong@linux.alibaba.com Signed-off-by: Vinod Koul --- drivers/dma/altera-msgdma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/altera-msgdma.c b/drivers/dma/altera-msgdma.c index 6f56dfd375e3..4153c2edb049 100644 --- a/drivers/dma/altera-msgdma.c +++ b/drivers/dma/altera-msgdma.c @@ -749,7 +749,7 @@ static irqreturn_t msgdma_irq_handler(int irq, void *data) } /** - * msgdma_chan_remove - Channel remove function + * msgdma_dev_remove() - Device remove function * @mdev: Pointer to the Altera mSGDMA device structure */ static void msgdma_dev_remove(struct msgdma_device *mdev) @@ -918,7 +918,7 @@ fail: } /** - * msgdma_dma_remove - Driver remove function + * msgdma_remove() - Driver remove function * @pdev: Pointer to the platform_device structure * * Return: Always '0' -- cgit v1.2.3 From 86cb0defe0e275453bc39e856bb523eb425a6537 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 8 Jul 2022 18:01:52 +0100 Subject: dmaengine: dw-axi-dmac: do not print NULL LLI during error During debugging we have seen an issue where axi_chan_dump_lli() is passed a NULL LLI pointer which ends up causing an OOPS due to trying to get fields from it. Simply print NULL LLI and exit to avoid this. Signed-off-by: Ben Dooks Link: https://lore.kernel.org/r/20220708170153.269991-3-ben.dooks@sifive.com Signed-off-by: Vinod Koul --- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index e9c9bcb1f5c2..abc2a919a11c 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -982,6 +982,11 @@ static int dw_axi_dma_chan_slave_config(struct dma_chan *dchan, static void axi_chan_dump_lli(struct axi_dma_chan *chan, struct axi_dma_hw_desc *desc) { + if (!desc->lli) { + dev_err(dchan2dev(&chan->vc.chan), "NULL LLI\n"); + return; + } + dev_err(dchan2dev(&chan->vc.chan), "SAR: 0x%llx DAR: 0x%llx LLP: 0x%llx BTS 0x%x CTL: 0x%x:%08x", le64_to_cpu(desc->lli->sar), -- cgit v1.2.3 From 820f5ce999d2f99961e88c16d65cd26764df0590 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 8 Jul 2022 18:01:53 +0100 Subject: dmaengine: dw-axi-dmac: ignore interrupt if no descriptor If the channel has no descriptor and the interrupt is raised then the kernel will OOPS. Check the result of vchan_next_desc() in the handler axi_chan_block_xfer_complete() to avoid the error happening. Signed-off-by: Ben Dooks Link: https://lore.kernel.org/r/20220708170153.269991-4-ben.dooks@sifive.com Signed-off-by: Vinod Koul --- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index abc2a919a11c..c62809dfeae3 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -1054,6 +1054,11 @@ static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan) /* The completed descriptor currently is in the head of vc list */ vd = vchan_next_desc(&chan->vc); + if (!vd) { + dev_err(chan2dev(chan), "BUG: %s, IRQ with no descriptors\n", + axi_chan_name(chan)); + goto out; + } if (chan->cyclic) { desc = vd_to_axi_desc(vd); @@ -1083,6 +1088,7 @@ static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan) axi_chan_start_first_queued(chan); } +out: spin_unlock_irqrestore(&chan->vc.lock, flags); } -- cgit v1.2.3 From c3266ee185b59e5aab3e0f982e5b7f95d31555a7 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 6 Jul 2022 08:13:27 -0300 Subject: dmaengine: imx-dma: Cast of_device_get_match_data() with (uintptr_t) Change the of_device_get_match_data() cast to (uintptr_t) to silence the following clang warning: drivers/dma/imx-dma.c:1048:20: warning: cast to smaller integer type 'enum imx_dma_type' from 'const void *' [-Wvoid-pointer-to-enum-cast] Reported-by: kernel test robot Fixes: 0ab785c894e6 ("dmaengine: imx-dma: Remove unused .id_table") Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20220706111327.940764-1-festevam@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/imx-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 3bffe3ecbd1b..65c6094ce063 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -1047,7 +1047,7 @@ static int __init imxdma_probe(struct platform_device *pdev) return -ENOMEM; imxdma->dev = &pdev->dev; - imxdma->devtype = (enum imx_dma_type)of_device_get_match_data(&pdev->dev); + imxdma->devtype = (uintptr_t)of_device_get_match_data(&pdev->dev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); imxdma->base = devm_ioremap_resource(&pdev->dev, res); -- cgit v1.2.3 From d0b55afa47694f6f61b40f578ede7bde1648fe48 Mon Sep 17 00:00:00 2001 From: Fenghua Yu Date: Wed, 6 Jul 2022 17:20:52 -0700 Subject: dmaengine: idxd: Correct IAX operation code names Some IAX operation code nomenclatures are misleading or don't match with others: 1. Operation code 0x4c is Zero Compress 32. IAX_OPCODE_DECOMP_32 is a misleading name. Change it to IAX_OPCODE_ZERO_COMP_32. 2. Operation code 0x4d is Zero Compress 16. IAX_OPCODE_DECOMP_16 is a misleading name. Change it to IAX_OPCODE_ZERO_COMP_16. 3. IAX_OPCDE_FIND_UNIQUE is corrected to match with other nomenclatures. Co-developed-by: Li Zhang Signed-off-by: Li Zhang Signed-off-by: Fenghua Yu Reviewed-by: Dave Jiang Link: https://lore.kernel.org/r/20220707002052.1546361-1-fenghua.yu@intel.com Signed-off-by: Vinod Koul --- include/uapi/linux/idxd.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/idxd.h b/include/uapi/linux/idxd.h index bce7c43657d5..095299c75828 100644 --- a/include/uapi/linux/idxd.h +++ b/include/uapi/linux/idxd.h @@ -89,14 +89,14 @@ enum iax_opcode { IAX_OPCODE_CRC64, IAX_OPCODE_ZERO_DECOMP_32 = 0x48, IAX_OPCODE_ZERO_DECOMP_16, - IAX_OPCODE_DECOMP_32 = 0x4c, - IAX_OPCODE_DECOMP_16, + IAX_OPCODE_ZERO_COMP_32 = 0x4c, + IAX_OPCODE_ZERO_COMP_16, IAX_OPCODE_SCAN = 0x50, IAX_OPCODE_SET_MEMBER, IAX_OPCODE_EXTRACT, IAX_OPCODE_SELECT, IAX_OPCODE_RLE_BURST, - IAX_OPCDE_FIND_UNIQUE, + IAX_OPCODE_FIND_UNIQUE, IAX_OPCODE_EXPAND, }; -- cgit v1.2.3 From e0c7ea83f006ce8c3264ef8b6508a891d886ad4f Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 7 Jul 2022 11:00:29 +0800 Subject: dmaengine: imx-sdma: Add FIFO stride support for multi FIFO script The peripheral may have several FIFOs, but some case just select some FIFOs from them for data transfer, which means FIFO0 and FIFO2 may be selected. So add FIFO address stride support, 0 means all FIFOs are continuous, 1 means 1 word stride between FIFOs. All stride between FIFOs should be same. Another option words_per_fifo means how many audio channel data copied to one FIFO one time, 1 means one channel per FIFO, 2 means 2 channels per FIFO. If 'n_fifos_src = 4' and 'words_per_fifo = 2', it means the first two words(channels) fetch from FIFO0 and then jump to FIFO1 for next two words, and so on after the last FIFO3 fetched, roll back to FIFO0. Signed-off-by: Joy Zou Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1657162829-9273-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Vinod Koul --- drivers/dma/imx-sdma.c | 27 +++++++++++++++++++++++++-- include/linux/dma/imx-dma.h | 13 +++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 8a5d4d4a4dff..e302089784ed 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -183,6 +183,8 @@ BIT(DMA_DEV_TO_DEV)) #define SDMA_WATERMARK_LEVEL_N_FIFOS GENMASK(15, 12) +#define SDMA_WATERMARK_LEVEL_OFF_FIFOS GENMASK(19, 16) +#define SDMA_WATERMARK_LEVEL_WORDS_PER_FIFO GENMASK(31, 28) #define SDMA_WATERMARK_LEVEL_SW_DONE BIT(23) #define SDMA_DONE0_CONFIG_DONE_SEL BIT(7) @@ -429,6 +431,9 @@ struct sdma_desc { * @n_fifos_src: number of source device fifos * @n_fifos_dst: number of destination device fifos * @sw_done: software done flag + * @stride_fifos_src: stride for source device FIFOs + * @stride_fifos_dst: stride for destination device FIFOs + * @words_per_fifo: copy number of words one time for one FIFO */ struct sdma_channel { struct virt_dma_chan vc; @@ -456,6 +461,9 @@ struct sdma_channel { bool is_ram_script; unsigned int n_fifos_src; unsigned int n_fifos_dst; + unsigned int stride_fifos_src; + unsigned int stride_fifos_dst; + unsigned int words_per_fifo; bool sw_done; }; @@ -1245,17 +1253,29 @@ static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac) static void sdma_set_watermarklevel_for_sais(struct sdma_channel *sdmac) { unsigned int n_fifos; + unsigned int stride_fifos; + unsigned int words_per_fifo; if (sdmac->sw_done) sdmac->watermark_level |= SDMA_WATERMARK_LEVEL_SW_DONE; - if (sdmac->direction == DMA_DEV_TO_MEM) + if (sdmac->direction == DMA_DEV_TO_MEM) { n_fifos = sdmac->n_fifos_src; - else + stride_fifos = sdmac->stride_fifos_src; + } else { n_fifos = sdmac->n_fifos_dst; + stride_fifos = sdmac->stride_fifos_dst; + } + + words_per_fifo = sdmac->words_per_fifo; sdmac->watermark_level |= FIELD_PREP(SDMA_WATERMARK_LEVEL_N_FIFOS, n_fifos); + sdmac->watermark_level |= + FIELD_PREP(SDMA_WATERMARK_LEVEL_OFF_FIFOS, stride_fifos); + if (words_per_fifo) + sdmac->watermark_level |= + FIELD_PREP(SDMA_WATERMARK_LEVEL_WORDS_PER_FIFO, (words_per_fifo - 1)); } static int sdma_config_channel(struct dma_chan *chan) @@ -1769,6 +1789,9 @@ static int sdma_config(struct dma_chan *chan, } sdmac->n_fifos_src = sdmacfg->n_fifos_src; sdmac->n_fifos_dst = sdmacfg->n_fifos_dst; + sdmac->stride_fifos_src = sdmacfg->stride_fifos_src; + sdmac->stride_fifos_dst = sdmacfg->stride_fifos_dst; + sdmac->words_per_fifo = sdmacfg->words_per_fifo; sdmac->sw_done = sdmacfg->sw_done; } diff --git a/include/linux/dma/imx-dma.h b/include/linux/dma/imx-dma.h index 8887762360d4..f487a4fa103a 100644 --- a/include/linux/dma/imx-dma.h +++ b/include/linux/dma/imx-dma.h @@ -70,6 +70,16 @@ static inline int imx_dma_is_general_purpose(struct dma_chan *chan) * struct sdma_peripheral_config - SDMA config for audio * @n_fifos_src: Number of FIFOs for recording * @n_fifos_dst: Number of FIFOs for playback + * @stride_fifos_src: FIFO address stride for recording, 0 means all FIFOs are + * continuous, 1 means 1 word stride between FIFOs. All stride + * between FIFOs should be same. + * @stride_fifos_dst: FIFO address stride for playback + * @words_per_fifo: numbers of words per FIFO fetch/fill, 1 means + * one channel per FIFO, 2 means 2 channels per FIFO.. + * If 'n_fifos_src = 4' and 'words_per_fifo = 2', it + * means the first two words(channels) fetch from FIFO0 + * and then jump to FIFO1 for next two words, and so on + * after the last FIFO3 fetched, roll back to FIFO0. * @sw_done: Use software done. Needed for PDM (micfil) * * Some i.MX Audio devices (SAI, micfil) have multiple successive FIFO @@ -82,6 +92,9 @@ static inline int imx_dma_is_general_purpose(struct dma_chan *chan) struct sdma_peripheral_config { int n_fifos_src; int n_fifos_dst; + int stride_fifos_src; + int stride_fifos_dst; + int words_per_fifo; bool sw_done; }; -- cgit v1.2.3 From f66d59180bae2f0e8979962c3df4d445b3ac50d0 Mon Sep 17 00:00:00 2001 From: XueBing Chen Date: Mon, 11 Jul 2022 22:05:33 +0800 Subject: dmaengine: xilinx: use strscpy to replace strlcpy The strlcpy should not be used because it doesn't limit the source length. Preferred is strscpy. Signed-off-by: XueBing Chen Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/39aa840f.e31.181ed9461c2.Coremail.chenxuebing@jari.cn Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_dpdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c index f708808d73ba..84dc5240a807 100644 --- a/drivers/dma/xilinx/xilinx_dpdma.c +++ b/drivers/dma/xilinx/xilinx_dpdma.c @@ -376,7 +376,7 @@ static ssize_t xilinx_dpdma_debugfs_read(struct file *f, char __user *buf, if (ret < 0) goto done; } else { - strlcpy(kern_buff, "No testcase executed", + strscpy(kern_buff, "No testcase executed", XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE); } -- cgit v1.2.3 From 37a0d69d00f50f2a0c387bbbbb2946e771af243d Mon Sep 17 00:00:00 2001 From: Akhil R Date: Wed, 20 Jul 2022 16:10:43 +0530 Subject: dt-bindings: dmaengine: Add compatible for Tegra234 Document the compatible string used by GPCDMA controller for Tegra234. Signed-off-by: Akhil R Reviewed-by: Jon Hunter Acked-by: Rob Herring Link: https://lore.kernel.org/r/20220720104045.16099-2-akhilrajeev@nvidia.com Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml b/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml index 9dd1476d1849..7e575296df0c 100644 --- a/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml +++ b/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml @@ -23,7 +23,9 @@ properties: oneOf: - const: nvidia,tegra186-gpcdma - items: - - const: nvidia,tegra194-gpcdma + - enum: + - nvidia,tegra234-gpcdma + - nvidia,tegra194-gpcdma - const: nvidia,tegra186-gpcdma "#dma-cells": -- cgit v1.2.3 From 36834c67016794b8fa03d7672a5b7f2cc4529298 Mon Sep 17 00:00:00 2001 From: Akhil R Date: Wed, 20 Jul 2022 16:10:44 +0530 Subject: dmaengine: tegra: Add terminate() for Tegra234 In certain cases where the DMA client bus gets corrupted or if the end device ceases to send/receive data, DMA can wait indefinitely for the data to be received/sent. Attempting to terminate the transfer will put the DMA in pause flush mode and it remains there. The channel is irrecoverable once this pause times out in Tegra194 and earlier chips. Whereas, from Tegra234, it can be recovered by disabling the channel and reprograming it. Hence add a new terminate() function that ignores the outcome of dma_pause() so that terminate_all() can proceed to disable the channel. Signed-off-by: Akhil R Reviewed-by: Jon Hunter Link: https://lore.kernel.org/r/20220720104045.16099-3-akhilrajeev@nvidia.com Signed-off-by: Vinod Koul --- drivers/dma/tegra186-gpc-dma.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c index 05cd451f541d..fa9bda4a2bc6 100644 --- a/drivers/dma/tegra186-gpc-dma.c +++ b/drivers/dma/tegra186-gpc-dma.c @@ -157,8 +157,8 @@ * If any burst is in flight and DMA paused then this is the time to complete * on-flight burst and update DMA status register. */ -#define TEGRA_GPCDMA_BURST_COMPLETE_TIME 20 -#define TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT 100 +#define TEGRA_GPCDMA_BURST_COMPLETE_TIME 10 +#define TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT 5000 /* 5 msec */ /* Channel base address offset from GPCDMA base address */ #define TEGRA_GPCDMA_CHANNEL_BASE_ADD_OFFSET 0x20000 @@ -432,6 +432,17 @@ static int tegra_dma_device_resume(struct dma_chan *dc) return 0; } +static inline int tegra_dma_pause_noerr(struct tegra_dma_channel *tdc) +{ + /* Return 0 irrespective of PAUSE status. + * This is useful to recover channels that can exit out of flush + * state when the channel is disabled. + */ + + tegra_dma_pause(tdc); + return 0; +} + static void tegra_dma_disable(struct tegra_dma_channel *tdc) { u32 csr, status; @@ -1292,6 +1303,14 @@ static const struct tegra_dma_chip_data tegra194_dma_chip_data = { .terminate = tegra_dma_pause, }; +static const struct tegra_dma_chip_data tegra234_dma_chip_data = { + .nr_channels = 31, + .channel_reg_size = SZ_64K, + .max_dma_count = SZ_1G, + .hw_support_pause = true, + .terminate = tegra_dma_pause_noerr, +}; + static const struct of_device_id tegra_dma_of_match[] = { { .compatible = "nvidia,tegra186-gpcdma", @@ -1299,6 +1318,9 @@ static const struct of_device_id tegra_dma_of_match[] = { }, { .compatible = "nvidia,tegra194-gpcdma", .data = &tegra194_dma_chip_data, + }, { + .compatible = "nvidia,tegra234-gpcdma", + .data = &tegra234_dma_chip_data, }, { }, }; -- cgit v1.2.3 From 1e42f82cbec7b2cc4873751e7791e6611901c5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 21 Jul 2022 22:40:54 +0200 Subject: dmaengine: sprd: Cleanup in .remove() after pm_runtime_get_sync() failed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's not allowed to quit remove early without cleaning up completely. Otherwise this results in resource leaks that probably yield graver problems later. Here for example some tasklets might survive the lifetime of the sprd-dma device and access sdev which is freed after .remove() returns. As none of the device freeing requires an active device, just ignore the return value of pm_runtime_get_sync(). Signed-off-by: Uwe Kleine-König Reviewed-by: Baolin Wang Link: https://lore.kernel.org/r/20220721204054.323602-1-u.kleine-koenig@pengutronix.de Signed-off-by: Vinod Koul --- drivers/dma/sprd-dma.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c index 2138b80435ab..474d3ba8ec9f 100644 --- a/drivers/dma/sprd-dma.c +++ b/drivers/dma/sprd-dma.c @@ -1237,11 +1237,8 @@ static int sprd_dma_remove(struct platform_device *pdev) { struct sprd_dma_dev *sdev = platform_get_drvdata(pdev); struct sprd_dma_chn *c, *cn; - int ret; - ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) - return ret; + pm_runtime_get_sync(&pdev->dev); /* explicitly free the irq */ if (sdev->irq > 0) -- cgit v1.2.3 From 7d3a3aaaa9cc8ec53e9ef4f3e1711827107f76c5 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 22 Jul 2022 09:44:30 +0100 Subject: dmaengine: sh: rz-dmac: Add device_synchronize callback Some on-chip peripheral modules(for eg:- rspi) on RZ/G2L SoC use the same signal for both interrupt and DMA transfer requests. The signal works as a DMA transfer request signal by setting DMARS, and subsequent interrupt requests to the interrupt controller are masked. We can re-enable the interrupt by clearing the DMARS. This patch adds device_synchronize callback for clearing DMARS and thereby allowing DMA consumers to switch to interrupt mode. Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20220722084430.969333-1-biju.das.jz@bp.renesas.com Signed-off-by: Vinod Koul --- drivers/dma/sh/rz-dmac.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c index ee2872e7d64c..476847a4916b 100644 --- a/drivers/dma/sh/rz-dmac.c +++ b/drivers/dma/sh/rz-dmac.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -630,6 +631,21 @@ static void rz_dmac_virt_desc_free(struct virt_dma_desc *vd) */ } +static void rz_dmac_device_synchronize(struct dma_chan *chan) +{ + struct rz_dmac_chan *channel = to_rz_dmac_chan(chan); + struct rz_dmac *dmac = to_rz_dmac(chan->device); + u32 chstat; + int ret; + + ret = read_poll_timeout(rz_dmac_ch_readl, chstat, !(chstat & CHSTAT_EN), + 100, 100000, false, channel, CHSTAT, 1); + if (ret < 0) + dev_warn(dmac->dev, "DMA Timeout"); + + rz_dmac_set_dmars_register(dmac, channel->index, 0); +} + /* * ----------------------------------------------------------------------------- * IRQ handling @@ -909,6 +925,7 @@ static int rz_dmac_probe(struct platform_device *pdev) engine->device_config = rz_dmac_config; engine->device_terminate_all = rz_dmac_terminate_all; engine->device_issue_pending = rz_dmac_issue_pending; + engine->device_synchronize = rz_dmac_device_synchronize; engine->copy_align = DMAENGINE_ALIGN_1_BYTE; dma_set_max_seg_size(engine->dev, U32_MAX); -- cgit v1.2.3 From 9327c7e7539371c6f202303d5539afbae006ec72 Mon Sep 17 00:00:00 2001 From: Mathias Tausen Date: Tue, 26 Jul 2022 16:02:12 +0200 Subject: dmaengine: axi-dmac: check cache coherency register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Marking the DMA as cache coherent (dma-coherent in devicetree) is only safe with versions of axi_dmac that have this feature enabled. Cc: Lars-Peter Clausen Cc: Vinod Koul Acked-by: Nuno Sá Signed-off-by: Mathias Tausen Link: https://lore.kernel.org/r/20220726140213.786939-1-mta@satlab.com Signed-off-by: Vinod Koul --- drivers/dma/dma-axi-dmac.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index 5161b73c30c4..f30dabc99795 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,9 @@ #define AXI_DMAC_DMA_DST_TYPE_GET(x) FIELD_GET(AXI_DMAC_DMA_DST_TYPE_MSK, x) #define AXI_DMAC_DMA_DST_WIDTH_MSK GENMASK(3, 0) #define AXI_DMAC_DMA_DST_WIDTH_GET(x) FIELD_GET(AXI_DMAC_DMA_DST_WIDTH_MSK, x) +#define AXI_DMAC_REG_COHERENCY_DESC 0x14 +#define AXI_DMAC_DST_COHERENT_MSK BIT(0) +#define AXI_DMAC_DST_COHERENT_GET(x) FIELD_GET(AXI_DMAC_DST_COHERENT_MSK, x) #define AXI_DMAC_REG_IRQ_MASK 0x80 #define AXI_DMAC_REG_IRQ_PENDING 0x84 @@ -979,6 +983,18 @@ static int axi_dmac_probe(struct platform_device *pdev) axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_MASK, 0x00); + if (of_dma_is_coherent(pdev->dev.of_node)) { + ret = axi_dmac_read(dmac, AXI_DMAC_REG_COHERENCY_DESC); + + if (version < ADI_AXI_PCORE_VER(4, 4, 'a') || + !AXI_DMAC_DST_COHERENT_GET(ret)) { + dev_err(dmac->dma_dev.dev, + "Coherent DMA not supported in hardware"); + ret = -EINVAL; + goto err_clk_disable; + } + } + ret = dma_async_device_register(dma_dev); if (ret) goto err_clk_disable; -- cgit v1.2.3 From a1873f837f9e5c1001462a635af1b0bab31aa9fd Mon Sep 17 00:00:00 2001 From: Slark Xiao Date: Thu, 21 Jul 2022 13:56:47 +0800 Subject: dmaengine: mediatek: mtk-hsdma: Fix typo 'the the' in comment Replace 'the the' with 'the' in the comment. Signed-off-by: Slark Xiao Link: https://lore.kernel.org/r/20220721055647.46085-1-slark_xiao@163.com Signed-off-by: Vinod Koul --- drivers/dma/mediatek/mtk-hsdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c index a72e5a096c5c..f7717c44b887 100644 --- a/drivers/dma/mediatek/mtk-hsdma.c +++ b/drivers/dma/mediatek/mtk-hsdma.c @@ -138,7 +138,7 @@ struct mtk_hsdma_vdesc { /** * struct mtk_hsdma_cb - This is the struct holding extra info required for RX - * ring to know what relevant VD the the PD is being + * ring to know what relevant VD the PD is being * mapped to. * @vd: Pointer to the relevant VD. * @flag: Flag indicating what action should be taken when VD -- cgit v1.2.3