From baf32519979f22e34db255117449fd91a4ad3c53 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Tue, 31 May 2022 15:50:14 +0200 Subject: [PATCH 001/111] 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: From 5f89b97e1fd5f5e6f1df78aade50d92ca7809b4b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 8 Jun 2022 17:42:01 +0200 Subject: [PATCH 002/111] 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; From e8ecf73adbb41ee00d5fbaf35c3edab252b5d30f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 8 Jun 2022 17:42:58 +0200 Subject: [PATCH 003/111] 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, From 23fbc87c8ae6f550a2c919370d44fd29cbb568aa Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 27 May 2022 23:55:08 +0200 Subject: [PATCH 004/111] 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 --------------- .../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>; + }; +... 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: [PATCH 005/111] 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>; + }; 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: [PATCH 006/111] 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"); 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: [PATCH 007/111] 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 From 11a72ae911d3d4eccfba8dbf21daca4ce5f1b6af Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 10 Jun 2022 10:01:17 +0530 Subject: [PATCH 008/111] 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)); From 2717d33841957a0f5fb65fd8b37f9c2321593864 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Thu, 9 Jun 2022 16:14:54 +0200 Subject: [PATCH 009/111] 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 = { From 7811f2e7fd6a30d96eaa1fccf57b07694a8cad27 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Thu, 9 Jun 2022 16:14:55 +0200 Subject: [PATCH 010/111] 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) { From c9357195c5770029f0c65a5b76756dea5b767ff0 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Fri, 10 Jun 2022 13:07:00 +0300 Subject: [PATCH 011/111] 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, From 62c427ca0745d54c7b715923633ced3e34453722 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 14 Jun 2022 09:25:03 -0600 Subject: [PATCH 012/111] 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>; From 81ce6f3dbbdce2785bba6e0b3c540793725c218d Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Mon, 13 Jun 2022 13:03:26 +0200 Subject: [PATCH 013/111] 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 From ce4b461ba2c1247e0508995ff250f156b5310441 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 16 Jun 2022 16:13:12 +0200 Subject: [PATCH 014/111] 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; From 5dc8638872ef0deeae1371a9e2d551920870f76a Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 15 Jun 2022 16:26:51 -0700 Subject: [PATCH 015/111] 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 From f7a03501b090f8c5f9ecb08420cda0b168667004 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Mon, 13 Jun 2022 01:23:58 +0300 Subject: [PATCH 016/111] 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); From 0cae04373b77a117830e5f7d7aaa7eaf01f950d5 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 6 Jun 2022 09:47:33 +0200 Subject: [PATCH 017/111] 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 --- .../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) { From 3a4413b77429b56bae725363392b56ea65c790c4 Mon Sep 17 00:00:00 2001 From: Jayesh Choudhary Date: Tue, 28 Jun 2022 10:32:32 +0530 Subject: [PATCH 018/111] 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), From 0951a90e343d20b62daa7720da61f124b1c32d71 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 23 Jun 2022 09:33:53 -0300 Subject: [PATCH 019/111] 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; From a7a5c1a93d83e5b6331d6ed94f1bcdb15cc9a6c0 Mon Sep 17 00:00:00 2001 From: Jiang Jian Date: Wed, 22 Jun 2022 22:31:58 +0800 Subject: [PATCH 020/111] 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. From cfa1927f8468c76e42d727693a3c2be1a9540ee1 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 20 Jun 2022 10:00:02 +0800 Subject: [PATCH 021/111] 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 ++++++++++++++++++ .../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>; -}; From ab356484dbb950b069b363e45681270eb14fd02c Mon Sep 17 00:00:00 2001 From: Xiang wangx Date: Sat, 18 Jun 2022 21:03:49 +0800 Subject: [PATCH 022/111] 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. */ From 8d8bbefa6a3397e6f730dd75ba5128d9d106d4ea Mon Sep 17 00:00:00 2001 From: Xiang wangx Date: Sat, 18 Jun 2022 21:01:20 +0800 Subject: [PATCH 023/111] 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)) { From 9bef4929fa21477d44b4934d02296c4d0126dd40 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 14 Jun 2022 19:47:59 +0100 Subject: [PATCH 024/111] 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; From a94a098a21c678c07c8a742e4a65e8aa2bebdf08 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 20 Jun 2022 22:13:50 -0500 Subject: [PATCH 025/111] 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); From 8f64c2a4c8b59fe6dfc29add92c55947b1299da3 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Thu, 19 May 2022 21:08:55 +0800 Subject: [PATCH 026/111] 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); From e4c4182f3c55648d427060da55ad6aa55269651a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:11:01 +0200 Subject: [PATCH 027/111] 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); From fd39ae75b66260f235b05e48246fe63e9ea1a0e5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:11:11 +0200 Subject: [PATCH 028/111] 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); From 2749416f7529993afc8dedaf7e3ce5e5114d40c1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:10:17 +0200 Subject: [PATCH 029/111] 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 From 6a4e9307cd3782f8e805fac970b9a240ab3078d6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:11:12 +0200 Subject: [PATCH 030/111] 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 From a0e02b8cfb0559dbaf0e1a79e4944d5ad0d914f2 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:10:56 +0200 Subject: [PATCH 031/111] 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 From 0d7c11af47aa3b065dc0bbc96d42baf411ce09e0 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:10:30 +0200 Subject: [PATCH 032/111] 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; /* From a71da24ce1f8f6844c6378ae394b5c4b31ff5725 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:10:27 +0200 Subject: [PATCH 033/111] 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. */ From 6bc7ea3c9b49c869f688d949bb473c4e1484894f Mon Sep 17 00:00:00 2001 From: XueBing Chen Date: Wed, 25 May 2022 17:03:03 +0800 Subject: [PATCH 034/111] 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); From 4ce653d7c651d6a9fc6d5db4275624ac8d856b99 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Tue, 5 Jul 2022 22:52:04 +0100 Subject: [PATCH 035/111] 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 --- .../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: From b2cc5c465c2cb8ab697c3fd6583c614e3f6cfbcc Mon Sep 17 00:00:00 2001 From: Viacheslav Mitrofanov Date: Fri, 1 Jul 2022 11:29:42 +0300 Subject: [PATCH 036/111] 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); } From 01eafd4b23805890dfe8b3e639f1bf299a6dbcf5 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 6 Jul 2022 13:45:09 +0800 Subject: [PATCH 037/111] 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; From 4348d99efa01fe030eb625495de8b9f3578b5c7d Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Wed, 6 Jul 2022 16:26:05 +0800 Subject: [PATCH 038/111] 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' From 70f832206fe72e9998b46363e8e59e89b0b757bc Mon Sep 17 00:00:00 2001 From: Yifeng Zhao Date: Wed, 4 May 2022 23:32:39 +0200 Subject: [PATCH 039/111] mmc: sdhci-of-dwcmshc: add reset call back for rockchip Socs The reset function build in the SDHCI will not reset the logic circuit related to the tuning function, which may cause data reading errors. Resetting the complete SDHCI controller through the reset controller fixes the issue. Signed-off-by: Yifeng Zhao [rebase, use optional variant of reset getter] Acked-by: Adrian Hunter Signed-off-by: Sebastian Reichel Link: https://lore.kernel.org/r/20220504213251.264819-10-sebastian.reichel@collabora.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-dwcmshc.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index bac874ab0b33..3a1b5ba36405 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "sdhci-pltfm.h" @@ -63,6 +64,7 @@ struct rk3568_priv { /* Rockchip specified optional clocks */ struct clk_bulk_data rockchip_clks[RK3568_MAX_CLKS]; + struct reset_control *reset; u8 txclk_tapnum; }; @@ -255,6 +257,21 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN); } +static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host); + struct rk35xx_priv *priv = dwc_priv->priv; + + if (mask & SDHCI_RESET_ALL && priv->reset) { + reset_control_assert(priv->reset); + udelay(1); + reset_control_deassert(priv->reset); + } + + sdhci_reset(host, mask); +} + static const struct sdhci_ops sdhci_dwcmshc_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, @@ -269,7 +286,7 @@ static const struct sdhci_ops sdhci_dwcmshc_rk3568_ops = { .set_bus_width = sdhci_set_bus_width, .set_uhs_signaling = dwcmshc_set_uhs_signaling, .get_max_clock = sdhci_pltfm_clk_get_max_clock, - .reset = sdhci_reset, + .reset = rk35xx_sdhci_reset, .adma_write_desc = dwcmshc_adma_write_desc, }; @@ -292,6 +309,13 @@ static int dwcmshc_rk3568_init(struct sdhci_host *host, struct dwcmshc_priv *dwc int err; struct rk3568_priv *priv = dwc_priv->priv; + priv->reset = devm_reset_control_array_get_optional_exclusive(mmc_dev(host->mmc)); + if (IS_ERR(priv->reset)) { + err = PTR_ERR(priv->reset); + dev_err(mmc_dev(host->mmc), "failed to get reset control %d\n", err); + return err; + } + priv->rockchip_clks[0].id = "axi"; priv->rockchip_clks[1].id = "block"; priv->rockchip_clks[2].id = "timer"; From 86e1a8e1f9b555af342c53ae06284eeeab9a4263 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Wed, 4 May 2022 23:32:40 +0200 Subject: [PATCH 040/111] mmc: sdhci-of-dwcmshc: rename rk3568 to rk35xx Prepare driver for rk3588 support by renaming the internal data structures. Acked-by: Adrian Hunter Signed-off-by: Sebastian Reichel Link: https://lore.kernel.org/r/20220504213251.264819-11-sebastian.reichel@collabora.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-dwcmshc.c | 46 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 3a1b5ba36405..f5fd88c7adef 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -56,14 +56,14 @@ #define DLL_LOCK_WO_TMOUT(x) \ ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0)) -#define RK3568_MAX_CLKS 3 +#define RK35xx_MAX_CLKS 3 #define BOUNDARY_OK(addr, len) \ ((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1))) -struct rk3568_priv { +struct rk35xx_priv { /* Rockchip specified optional clocks */ - struct clk_bulk_data rockchip_clks[RK3568_MAX_CLKS]; + struct clk_bulk_data rockchip_clks[RK35xx_MAX_CLKS]; struct reset_control *reset; u8 txclk_tapnum; }; @@ -178,7 +178,7 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host); - struct rk3568_priv *priv = dwc_priv->priv; + struct rk35xx_priv *priv = dwc_priv->priv; u8 txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT; u32 extra, reg; int err; @@ -281,7 +281,7 @@ static const struct sdhci_ops sdhci_dwcmshc_ops = { .adma_write_desc = dwcmshc_adma_write_desc, }; -static const struct sdhci_ops sdhci_dwcmshc_rk3568_ops = { +static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = { .set_clock = dwcmshc_rk3568_set_clock, .set_bus_width = sdhci_set_bus_width, .set_uhs_signaling = dwcmshc_set_uhs_signaling, @@ -296,18 +296,18 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = { .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, }; -static const struct sdhci_pltfm_data sdhci_dwcmshc_rk3568_pdata = { - .ops = &sdhci_dwcmshc_rk3568_ops, +static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = { + .ops = &sdhci_dwcmshc_rk35xx_ops, .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN, }; -static int dwcmshc_rk3568_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv) +static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv) { int err; - struct rk3568_priv *priv = dwc_priv->priv; + struct rk35xx_priv *priv = dwc_priv->priv; priv->reset = devm_reset_control_array_get_optional_exclusive(mmc_dev(host->mmc)); if (IS_ERR(priv->reset)) { @@ -319,14 +319,14 @@ static int dwcmshc_rk3568_init(struct sdhci_host *host, struct dwcmshc_priv *dwc priv->rockchip_clks[0].id = "axi"; priv->rockchip_clks[1].id = "block"; priv->rockchip_clks[2].id = "timer"; - err = devm_clk_bulk_get_optional(mmc_dev(host->mmc), RK3568_MAX_CLKS, + err = devm_clk_bulk_get_optional(mmc_dev(host->mmc), RK35xx_MAX_CLKS, priv->rockchip_clks); if (err) { dev_err(mmc_dev(host->mmc), "failed to get clocks %d\n", err); return err; } - err = clk_bulk_prepare_enable(RK3568_MAX_CLKS, priv->rockchip_clks); + err = clk_bulk_prepare_enable(RK35xx_MAX_CLKS, priv->rockchip_clks); if (err) { dev_err(mmc_dev(host->mmc), "failed to enable clocks %d\n", err); return err; @@ -348,7 +348,7 @@ static int dwcmshc_rk3568_init(struct sdhci_host *host, struct dwcmshc_priv *dwc static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { { .compatible = "rockchip,rk3568-dwcmshc", - .data = &sdhci_dwcmshc_rk3568_pdata, + .data = &sdhci_dwcmshc_rk35xx_pdata, }, { .compatible = "snps,dwcmshc-sdhci", @@ -371,7 +371,7 @@ static int dwcmshc_probe(struct platform_device *pdev) struct sdhci_pltfm_host *pltfm_host; struct sdhci_host *host; struct dwcmshc_priv *priv; - struct rk3568_priv *rk_priv = NULL; + struct rk35xx_priv *rk_priv = NULL; const struct sdhci_pltfm_data *pltfm_data; int err; u32 extra; @@ -426,8 +426,8 @@ static int dwcmshc_probe(struct platform_device *pdev) host->mmc_host_ops.request = dwcmshc_request; host->mmc_host_ops.hs400_enhanced_strobe = dwcmshc_hs400_enhanced_strobe; - if (pltfm_data == &sdhci_dwcmshc_rk3568_pdata) { - rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk3568_priv), GFP_KERNEL); + if (pltfm_data == &sdhci_dwcmshc_rk35xx_pdata) { + rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk35xx_priv), GFP_KERNEL); if (!rk_priv) { err = -ENOMEM; goto err_clk; @@ -435,7 +435,7 @@ static int dwcmshc_probe(struct platform_device *pdev) priv->priv = rk_priv; - err = dwcmshc_rk3568_init(host, priv); + err = dwcmshc_rk35xx_init(host, priv); if (err) goto err_clk; } @@ -452,7 +452,7 @@ err_clk: clk_disable_unprepare(pltfm_host->clk); clk_disable_unprepare(priv->bus_clk); if (rk_priv) - clk_bulk_disable_unprepare(RK3568_MAX_CLKS, + clk_bulk_disable_unprepare(RK35xx_MAX_CLKS, rk_priv->rockchip_clks); free_pltfm: sdhci_pltfm_free(pdev); @@ -464,14 +464,14 @@ static int dwcmshc_remove(struct platform_device *pdev) struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); - struct rk3568_priv *rk_priv = priv->priv; + struct rk35xx_priv *rk_priv = priv->priv; sdhci_remove_host(host, 0); clk_disable_unprepare(pltfm_host->clk); clk_disable_unprepare(priv->bus_clk); if (rk_priv) - clk_bulk_disable_unprepare(RK3568_MAX_CLKS, + clk_bulk_disable_unprepare(RK35xx_MAX_CLKS, rk_priv->rockchip_clks); sdhci_pltfm_free(pdev); @@ -484,7 +484,7 @@ static int dwcmshc_suspend(struct device *dev) struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); - struct rk3568_priv *rk_priv = priv->priv; + struct rk35xx_priv *rk_priv = priv->priv; int ret; ret = sdhci_suspend_host(host); @@ -496,7 +496,7 @@ static int dwcmshc_suspend(struct device *dev) clk_disable_unprepare(priv->bus_clk); if (rk_priv) - clk_bulk_disable_unprepare(RK3568_MAX_CLKS, + clk_bulk_disable_unprepare(RK35xx_MAX_CLKS, rk_priv->rockchip_clks); return ret; @@ -507,7 +507,7 @@ static int dwcmshc_resume(struct device *dev) struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); - struct rk3568_priv *rk_priv = priv->priv; + struct rk35xx_priv *rk_priv = priv->priv; int ret; ret = clk_prepare_enable(pltfm_host->clk); @@ -521,7 +521,7 @@ static int dwcmshc_resume(struct device *dev) } if (rk_priv) { - ret = clk_bulk_prepare_enable(RK3568_MAX_CLKS, + ret = clk_bulk_prepare_enable(RK35xx_MAX_CLKS, rk_priv->rockchip_clks); if (ret) return ret; From c6f361cba51c536e7a6af31973c6a4e5d7e4e2e4 Mon Sep 17 00:00:00 2001 From: Yifeng Zhao Date: Wed, 4 May 2022 23:32:41 +0200 Subject: [PATCH 041/111] mmc: sdhci-of-dwcmshc: add support for rk3588 Add support for RK3588's DWCMSHC controller, which is used for providing the rootfs on the RK3588 evaluation board. Signed-off-by: Yifeng Zhao [port from vendor BSP] Acked-by: Adrian Hunter Signed-off-by: Sebastian Reichel Link: https://lore.kernel.org/r/20220504213251.264819-12-sebastian.reichel@collabora.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-dwcmshc.c | 121 +++++++++++++++++++++++----- 1 file changed, 103 insertions(+), 18 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index f5fd88c7adef..4e904850973c 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -31,6 +31,7 @@ /* Offset inside the vendor area 1 */ #define DWCMSHC_HOST_CTRL3 0x8 #define DWCMSHC_EMMC_CONTROL 0x2c +#define DWCMSHC_CARD_IS_EMMC BIT(0) #define DWCMSHC_ENHANCED_STROBE BIT(8) #define DWCMSHC_EMMC_ATCTRL 0x40 @@ -39,7 +40,7 @@ #define DWCMSHC_EMMC_DLL_RXCLK 0x804 #define DWCMSHC_EMMC_DLL_TXCLK 0x808 #define DWCMSHC_EMMC_DLL_STRBIN 0x80c -#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24) +#define DECMSHC_EMMC_DLL_CMDOUT 0x810 #define DWCMSHC_EMMC_DLL_STATUS0 0x840 #define DWCMSHC_EMMC_DLL_START BIT(0) #define DWCMSHC_EMMC_DLL_LOCKED BIT(8) @@ -48,11 +49,21 @@ #define DWCMSHC_EMMC_DLL_START_POINT 16 #define DWCMSHC_EMMC_DLL_INC 8 #define DWCMSHC_EMMC_DLL_DLYENA BIT(27) -#define DLL_TXCLK_TAPNUM_DEFAULT 0x8 -#define DLL_STRBIN_TAPNUM_DEFAULT 0x8 +#define DLL_TXCLK_TAPNUM_DEFAULT 0x10 +#define DLL_TXCLK_TAPNUM_90_DEGREES 0xA #define DLL_TXCLK_TAPNUM_FROM_SW BIT(24) +#define DLL_STRBIN_TAPNUM_DEFAULT 0x8 +#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24) +#define DLL_STRBIN_DELAY_NUM_SEL BIT(26) +#define DLL_STRBIN_DELAY_NUM_OFFSET 16 +#define DLL_STRBIN_DELAY_NUM_DEFAULT 0x16 #define DLL_RXCLK_NO_INVERTER 1 #define DLL_RXCLK_INVERTER 0 +#define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8 +#define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24) +#define DLL_CMDOUT_SRC_CLK_NEG BIT(28) +#define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29) + #define DLL_LOCK_WO_TMOUT(x) \ ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0)) @@ -61,10 +72,16 @@ #define BOUNDARY_OK(addr, len) \ ((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1))) +enum dwcmshc_rk_type { + DWCMSHC_RK3568, + DWCMSHC_RK3588, +}; + struct rk35xx_priv { /* Rockchip specified optional clocks */ struct clk_bulk_data rockchip_clks[RK35xx_MAX_CLKS]; struct reset_control *reset; + enum dwcmshc_rk_type devtype; u8 txclk_tapnum; }; @@ -133,7 +150,9 @@ static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq) static void dwcmshc_set_uhs_signaling(struct sdhci_host *host, unsigned int timing) { - u16 ctrl_2; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); + u16 ctrl, ctrl_2; ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); /* Select Bus Speed Mode for host */ @@ -151,8 +170,15 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host, else if ((timing == MMC_TIMING_UHS_DDR50) || (timing == MMC_TIMING_MMC_DDR52)) ctrl_2 |= SDHCI_CTRL_UHS_DDR50; - else if (timing == MMC_TIMING_MMC_HS400) + else if (timing == MMC_TIMING_MMC_HS400) { + /* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */ + ctrl = sdhci_readw(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL); + ctrl |= DWCMSHC_CARD_IS_EMMC; + sdhci_writew(host, ctrl, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL); + ctrl_2 |= DWCMSHC_CTRL_HS400; + } + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); } @@ -185,17 +211,11 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock host->mmc->actual_clock = 0; - /* - * DO NOT TOUCH THIS SETTING. RX clk inverter unit is enabled - * by default, but it shouldn't be enabled. We should anyway - * disable it before issuing any cmds. - */ - extra = DWCMSHC_EMMC_DLL_DLYENA | - DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; - sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); - - if (clock == 0) + if (clock == 0) { + /* Disable interface clock at initial state. */ + sdhci_set_clock(host, clock); return; + } /* Rockchip platform only support 375KHz for identify mode */ if (clock <= 400000) @@ -213,9 +233,21 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock extra &= ~BIT(0); sdhci_writel(host, extra, reg); - if (clock <= 400000) { - /* Disable DLL to reset sample clock */ + if (clock <= 52000000) { + /* Disable DLL and reset both of sample and drive clock */ sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_RXCLK); + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK); + sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT); + /* + * Before switching to hs400es mode, the driver will enable + * enhanced strobe first. PHY needs to configure the parameters + * of enhanced strobe first. + */ + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_STRBIN_DELAY_NUM_SEL | + DLL_STRBIN_DELAY_NUM_DEFAULT << DLL_STRBIN_DELAY_NUM_OFFSET; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN); return; } @@ -224,6 +256,15 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock udelay(1); sdhci_writel(host, 0x0, DWCMSHC_EMMC_DLL_CTRL); + /* + * We shouldn't set DLL_RXCLK_NO_INVERTER for identify mode but + * we must set it in higher speed mode. + */ + extra = DWCMSHC_EMMC_DLL_DLYENA; + if (priv->devtype == DWCMSHC_RK3568) + extra |= DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); + /* Init DLL settings */ extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT | 0x2 << DWCMSHC_EMMC_DLL_INC | @@ -246,8 +287,20 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock host->mmc->ios.timing == MMC_TIMING_MMC_HS400) txclk_tapnum = priv->txclk_tapnum; + if ((priv->devtype == DWCMSHC_RK3588) && host->mmc->ios.timing == MMC_TIMING_MMC_HS400) { + txclk_tapnum = DLL_TXCLK_TAPNUM_90_DEGREES; + + extra = DLL_CMDOUT_SRC_CLK_NEG | + DLL_CMDOUT_EN_SRC_CLK_NEG | + DWCMSHC_EMMC_DLL_DLYENA | + DLL_CMDOUT_TAPNUM_90_DEGREES | + DLL_CMDOUT_TAPNUM_FROM_SW; + sdhci_writel(host, extra, DECMSHC_EMMC_DLL_CMDOUT); + } + extra = DWCMSHC_EMMC_DLL_DLYENA | DLL_TXCLK_TAPNUM_FROM_SW | + DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL | txclk_tapnum; sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK); @@ -345,7 +398,25 @@ static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc return 0; } +static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv) +{ + /* + * Don't support highspeed bus mode with low clk speed as we + * cannot use DLL for this condition. + */ + if (host->mmc->f_max <= 52000000) { + dev_info(mmc_dev(host->mmc), "Disabling HS200/HS400, frequency too low (%d)\n", + host->mmc->f_max); + host->mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400); + host->mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR); + } +} + static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { + { + .compatible = "rockchip,rk3588-dwcmshc", + .data = &sdhci_dwcmshc_rk35xx_pdata, + }, { .compatible = "rockchip,rk3568-dwcmshc", .data = &sdhci_dwcmshc_rk35xx_pdata, @@ -433,6 +504,11 @@ static int dwcmshc_probe(struct platform_device *pdev) goto err_clk; } + if (of_device_is_compatible(pdev->dev.of_node, "rockchip,rk3588-dwcmshc")) + rk_priv->devtype = DWCMSHC_RK3588; + else + rk_priv->devtype = DWCMSHC_RK3568; + priv->priv = rk_priv; err = dwcmshc_rk35xx_init(host, priv); @@ -442,12 +518,21 @@ static int dwcmshc_probe(struct platform_device *pdev) host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; - err = sdhci_add_host(host); + err = sdhci_setup_host(host); if (err) goto err_clk; + if (rk_priv) + dwcmshc_rk35xx_postinit(host, priv); + + err = __sdhci_add_host(host); + if (err) + goto err_setup_host; + return 0; +err_setup_host: + sdhci_cleanup_host(host); err_clk: clk_disable_unprepare(pltfm_host->clk); clk_disable_unprepare(priv->bus_clk); From 8574adf5222d786b747022c6edcbcdddf409a139 Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Sun, 15 May 2022 03:31:16 +0530 Subject: [PATCH 042/111] dt-bindings: mmc: sdhci-msm: Fix issues in yaml bindings Rob pointed some remaining issues in the sdhci-msm yaml bindings (via [1]). Fix the same by first using the 'mmc-controller.yaml' as 'ref' and thereafter also fix the issues reported by 'make dtbs_check' check. [1]. https://lore.kernel.org/linux-arm-msm/YnLmNCwNfoqZln12@robh.at.kernel.org/ Fixes: a45537723f4b ("dt-bindings: mmc: sdhci-msm: Convert bindings to yaml") Cc: Bjorn Andersson Cc: Rob Herring Cc: Ulf Hansson Signed-off-by: Bhupesh Sharma Link: https://lore.kernel.org/r/20220514220116.1008254-1-bhupesh.sharma@linaro.org Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/sdhci-msm.yaml | 52 ++++++++++++++++--- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index e4236334e748..31a3ce208e1a 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -17,6 +17,9 @@ description: properties: compatible: oneOf: + - enum: + - qcom,sdhci-msm-v4 + deprecated: true - items: - enum: - qcom,apq8084-sdhci @@ -27,6 +30,9 @@ properties: - qcom,msm8992-sdhci - qcom,msm8994-sdhci - qcom,msm8996-sdhci + - const: qcom,sdhci-msm-v4 # for sdcc versions less than 5.0 + - items: + - enum: - qcom,qcs404-sdhci - qcom,sc7180-sdhci - qcom,sc7280-sdhci @@ -38,12 +44,7 @@ properties: - qcom,sm6350-sdhci - qcom,sm8150-sdhci - qcom,sm8250-sdhci - - enum: - - qcom,sdhci-msm-v4 # for sdcc versions less than 5.0 - - qcom,sdhci-msm-v5 # for sdcc version 5.0 - - items: - - const: qcom,sdhci-msm-v4 # Deprecated (only for backward compatibility) - # for sdcc versions less than 5.0 + - const: qcom,sdhci-msm-v5 # for sdcc version 5.0 reg: minItems: 1 @@ -53,6 +54,28 @@ properties: - description: CQE register map - description: Inline Crypto Engine register map + reg-names: + minItems: 1 + maxItems: 4 + oneOf: + - items: + - const: hc_mem + - items: + - const: hc_mem + - const: core_mem + - items: + - const: hc_mem + - const: cqe_mem + - items: + - const: hc_mem + - const: cqe_mem + - const: ice_mem + - items: + - const: hc_mem + - const: core_mem + - const: cqe_mem + - const: ice_mem + clocks: minItems: 3 items: @@ -121,6 +144,16 @@ properties: description: A phandle to sdhci power domain node maxItems: 1 + mmc-ddr-1_8v: true + + mmc-hs200-1_8v: true + + mmc-hs400-1_8v: true + + bus-width: true + + max-frequency: true + patternProperties: '^opp-table(-[a-z0-9]+)?$': if: @@ -140,7 +173,10 @@ required: - clock-names - interrupts -additionalProperties: true +allOf: + - $ref: mmc-controller.yaml# + +unevaluatedProperties: false examples: - | @@ -149,7 +185,7 @@ examples: #include #include - sdhc_2: sdhci@8804000 { + sdhc_2: mmc@8804000 { compatible = "qcom,sm8250-sdhci", "qcom,sdhci-msm-v5"; reg = <0 0x08804000 0 0x1000>; From 2f8690ef64128bcbda24f0c426dff59835df7fbf Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Fri, 20 May 2022 14:31:07 -0400 Subject: [PATCH 043/111] dt-bindings: mmc: Add Broadcom optional sdio_freq clock The 72116B0 has improved SDIO controllers that allow the max clock rate to be increased from a max of 100MHz to a max of 150MHz. Optional "sdio_freq" clock is used to drive the bus clock if present optional property "clock-frequency" specifies a base clock frequency in Hz that overrides the base clock frequency in the CAPS registers. Signed-off-by: Kamal Dasu Reviewed-by: Krzysztof Kozlowski Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20220520183108.47358-2-kdasu.kdev@gmail.com Signed-off-by: Ulf Hansson --- .../bindings/mmc/brcm,sdhci-brcmstb.yaml | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml index 5ecdac9de484..dead421e17d6 100644 --- a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml +++ b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml @@ -10,9 +10,6 @@ maintainers: - Al Cooper - Florian Fainelli -allOf: - - $ref: mmc-controller.yaml# - properties: compatible: oneOf: @@ -42,23 +39,46 @@ properties: maxItems: 1 clocks: - maxItems: 1 - description: - handle to core clock for the sdhci controller. + minItems: 1 + items: + - description: handle to core clock for the sdhci controller + - description: handle to improved 150Mhz clock for sdhci controller (Optional clock) clock-names: + minItems: 1 items: - const: sw_sdio + - const: sdio_freq # Optional clock + + clock-frequency: + description: + Maximum operating frequency of sdio_freq sdhci controller clock + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 100000000 + maximum: 150000000 sdhci,auto-cmd12: type: boolean description: Specifies that controller should use auto CMD12 +allOf: + - $ref: mmc-controller.yaml# + - if: + properties: + clock-names: + contains: + const: sdio_freq + + then: + required: + - clock-frequency + required: - compatible - reg - interrupts - clocks + - clock-names unevaluatedProperties: false From 97904a59855c7ac7c613085bc6bdc550d48524ff Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Fri, 20 May 2022 14:31:08 -0400 Subject: [PATCH 044/111] mmc: sdhci-brcmstb: Add ability to increase max clock rate for 72116b0 The 72116B0 has improved SDIO controllers that allow the max clock rate to be increased from a max of 100MHz to a max of 150MHz. The driver will need to get the clock and increase it's default rate and override the caps register, that still indicates a max of 100MHz. The new clock will be named "sdio_freq" in the DT node's "clock-names" list. The driver will use a DT property, "clock-frequency", to enable this functionality and will get the actual rate in MHz from the property to allow various speeds to be requested. Signed-off-by: Al Cooper Signed-off-by: Kamal Dasu Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20220520183108.47358-3-kdasu.kdev@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-brcmstb.c | 69 +++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 8eb57de48e0c..f8dff8537920 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -31,6 +31,8 @@ struct sdhci_brcmstb_priv { void __iomem *cfg_regs; unsigned int flags; + struct clk *base_clk; + u32 base_freq_hz; }; struct brcmstb_match_priv { @@ -250,9 +252,11 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) struct sdhci_pltfm_host *pltfm_host; const struct of_device_id *match; struct sdhci_brcmstb_priv *priv; + u32 actual_clock_mhz; struct sdhci_host *host; struct resource *iomem; struct clk *clk; + struct clk *base_clk; int res; match = of_match_node(sdhci_brcm_of_match, pdev->dev.of_node); @@ -330,6 +334,35 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) if (match_priv->flags & BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT) host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; + /* Change the base clock frequency if the DT property exists */ + if (device_property_read_u32(&pdev->dev, "clock-frequency", + &priv->base_freq_hz) != 0) + goto add_host; + + base_clk = devm_clk_get_optional(&pdev->dev, "sdio_freq"); + if (IS_ERR(base_clk)) { + dev_warn(&pdev->dev, "Clock for \"sdio_freq\" not found\n"); + goto add_host; + } + + res = clk_prepare_enable(base_clk); + if (res) + goto err; + + /* set improved clock rate */ + clk_set_rate(base_clk, priv->base_freq_hz); + actual_clock_mhz = clk_get_rate(base_clk) / 1000000; + + host->caps &= ~SDHCI_CLOCK_V3_BASE_MASK; + host->caps |= (actual_clock_mhz << SDHCI_CLOCK_BASE_SHIFT); + /* Disable presets because they are now incorrect */ + host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; + + dev_dbg(&pdev->dev, "Base Clock Frequency changed to %dMHz\n", + actual_clock_mhz); + priv->base_clk = base_clk; + +add_host: res = sdhci_brcmstb_add_host(host, priv); if (res) goto err; @@ -340,6 +373,7 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) err: sdhci_pltfm_free(pdev); err_clk: + clk_disable_unprepare(base_clk); clk_disable_unprepare(clk); return res; } @@ -351,11 +385,44 @@ static void sdhci_brcmstb_shutdown(struct platform_device *pdev) MODULE_DEVICE_TABLE(of, sdhci_brcm_of_match); +#ifdef CONFIG_PM_SLEEP +static int sdhci_brcmstb_suspend(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host); + + clk_disable_unprepare(priv->base_clk); + return sdhci_pltfm_suspend(dev); +} + +static int sdhci_brcmstb_resume(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host); + int ret; + + ret = sdhci_pltfm_resume(dev); + if (!ret && priv->base_freq_hz) { + ret = clk_prepare_enable(priv->base_clk); + if (!ret) + ret = clk_set_rate(priv->base_clk, priv->base_freq_hz); + } + + return ret; +} +#endif + +static const struct dev_pm_ops sdhci_brcmstb_pmops = { + SET_SYSTEM_SLEEP_PM_OPS(sdhci_brcmstb_suspend, sdhci_brcmstb_resume) +}; + static struct platform_driver sdhci_brcmstb_driver = { .driver = { .name = "sdhci-brcmstb", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .pm = &sdhci_pltfm_pmops, + .pm = &sdhci_brcmstb_pmops, .of_match_table = of_match_ptr(sdhci_brcm_of_match), }, .probe = sdhci_brcmstb_probe, From b5899a3e2f783a27b268e38d37f9b24c71bddf45 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Mon, 23 May 2022 18:42:54 +0400 Subject: [PATCH 045/111] mmc: sdhci-of-esdhc: Fix refcount leak in esdhc_signal_voltage_switch of_find_matching_node() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Add missing of_node_put() to avoid refcount leak. of_node_put() checks null pointer. Fixes: ea35645a3c66 ("mmc: sdhci-of-esdhc: add support for signal voltage switch") Signed-off-by: Miaoqian Lin Link: https://lore.kernel.org/r/20220523144255.10310-1-linmq006@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-esdhc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index d9dc41143bb3..8b3d8119f388 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -904,6 +904,7 @@ static int esdhc_signal_voltage_switch(struct mmc_host *mmc, scfg_node = of_find_matching_node(NULL, scfg_device_ids); if (scfg_node) scfg_base = of_iomap(scfg_node, 0); + of_node_put(scfg_node); if (scfg_base) { sdhciovselcr = SDHCIOVSELCR_TGLEN | SDHCIOVSELCR_VSELVAL; From 7dc65e3c0ef4b746a583b7c58f99873fddf5ccfa Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 25 May 2022 22:00:22 -0300 Subject: [PATCH 046/111] mmc: mxcmmc: Silence a clang warning Change the of_device_get_match_data() cast to (uintptr_t) to silence the following clang warning: drivers/mmc/host/mxcmmc.c:1028:18: warning: cast to smaller integer type 'enum mxcmci_type' from 'const void *' [-Wvoid-pointer-to-enum-cast] Reported-by: kernel test robot Fixes: 8223e885e74b ("mmc: mxc: Convert the driver to DT-only") Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20220526010022.1163483-1-festevam@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mxcmmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index de04b5afef2e..613f13306433 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -1025,7 +1025,7 @@ static int mxcmci_probe(struct platform_device *pdev) mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; mmc->max_seg_size = mmc->max_req_size; - host->devtype = (enum mxcmci_type)of_device_get_match_data(&pdev->dev); + host->devtype = (uintptr_t)of_device_get_match_data(&pdev->dev); /* adjust max_segs after devtype detection */ if (!is_mpc512x_mmc(host)) From f0c88b04f3c229b1d4e2defeeb7e399d171a38e6 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Mon, 30 May 2022 14:38:56 +0200 Subject: [PATCH 047/111] mmc: mtk-sd: fix typo Fix a typo: Fianl -> Final. Signed-off-by: Fabien Parent Reviewed-by: Miles Chen Link: https://lore.kernel.org/r/20220530123857.692076-1-fparent@baylibre.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mtk-sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 9da4489dc345..a4954b200d87 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -2319,7 +2319,7 @@ static int msdc_execute_hs400_tuning(struct mmc_host *mmc, struct mmc_card *card else val = readl(host->base + PAD_DS_TUNE); - dev_info(host->dev, "Fianl PAD_DS_TUNE: 0x%x\n", val); + dev_info(host->dev, "Final PAD_DS_TUNE: 0x%x\n", val); return 0; From 91f059c95c6a5dbc0907a5f871e7915a5e93c1f9 Mon Sep 17 00:00:00 2001 From: Shaik Sajida Bhanu Date: Fri, 27 May 2022 23:23:52 +0530 Subject: [PATCH 048/111] mmc: core: Capture eMMC and SD card errors Add changes to capture eMMC and SD card errors. This is useful for debug and testing. Signed-off-by: Liangliang Lu Signed-off-by: Sayali Lokhande Signed-off-by: Bao D. Nguyen Signed-off-by: Ram Prakash Gupta Signed-off-by: Shaik Sajida Bhanu Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/1653674036-21829-2-git-send-email-quic_c_sbhanu@quicinc.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/core.c | 10 +++++++++- include/linux/mmc/host.h | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 4b70cbfc6d5d..ef53a2578824 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -943,9 +943,11 @@ int mmc_execute_tuning(struct mmc_card *card) } /* Only print error when we don't check for card removal */ - if (!host->detect_change) + if (!host->detect_change) { pr_err("%s: tuning execution failed: %d\n", mmc_hostname(host), err); + mmc_debugfs_err_stats_inc(host, MMC_ERR_TUNING); + } return err; } @@ -2244,6 +2246,12 @@ void mmc_rescan(struct work_struct *work) if (freqs[i] <= host->f_min) break; } + + /* + * Ignore the command timeout errors observed during + * the card init as those are excepted. + */ + host->err_stats[MMC_ERR_CMD_TIMEOUT] = 0; mmc_release_host(host); out: diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c193c50ccd78..eb8bc5b9b0b7 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -93,6 +93,25 @@ struct mmc_clk_phase_map { struct mmc_host; +enum mmc_err_stat { + MMC_ERR_CMD_TIMEOUT, + MMC_ERR_CMD_CRC, + MMC_ERR_DAT_TIMEOUT, + MMC_ERR_DAT_CRC, + MMC_ERR_AUTO_CMD, + MMC_ERR_ADMA, + MMC_ERR_TUNING, + MMC_ERR_CMDQ_RED, + MMC_ERR_CMDQ_GCE, + MMC_ERR_CMDQ_ICCE, + MMC_ERR_REQ_TIMEOUT, + MMC_ERR_CMDQ_REQ_TIMEOUT, + MMC_ERR_ICE_CFG, + MMC_ERR_CTRL_TIMEOUT, + MMC_ERR_UNEXPECTED_IRQ, + MMC_ERR_MAX, +}; + struct mmc_host_ops { /* * It is optional for the host to implement pre_req and post_req in @@ -501,6 +520,7 @@ struct mmc_host { /* Host Software Queue support */ bool hsq_enabled; + u32 err_stats[MMC_ERR_MAX]; unsigned long private[] ____cacheline_aligned; }; @@ -635,6 +655,12 @@ static inline enum dma_data_direction mmc_get_dma_dir(struct mmc_data *data) return data->flags & MMC_DATA_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE; } +static inline void mmc_debugfs_err_stats_inc(struct mmc_host *host, + enum mmc_err_stat stat) +{ + host->err_stats[stat] += 1; +} + int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error); int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode); int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); From efe8f5c9b5e118070f424205078ababc46fd130a Mon Sep 17 00:00:00 2001 From: Shaik Sajida Bhanu Date: Fri, 27 May 2022 23:23:53 +0530 Subject: [PATCH 049/111] mmc: sdhci: Capture eMMC and SD card errors Add changes to capture eMMC and SD card errors. This is useful for debug and testing. Signed-off-by: Liangliang Lu Signed-off-by: Sayali Lokhande Signed-off-by: Bao D. Nguyen Signed-off-by: Shaik Sajida Bhanu Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/1653674036-21829-3-git-send-email-quic_c_sbhanu@quicinc.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 59 ++++++++++++++++++++++++++++++---------- drivers/mmc/host/sdhci.h | 3 ++ include/linux/mmc/mmc.h | 6 ++++ 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 22152029e14c..7689ffec5ad1 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -224,6 +224,7 @@ void sdhci_reset(struct sdhci_host *host, u8 mask) if (timedout) { pr_err("%s: Reset 0x%x never completed.\n", mmc_hostname(host->mmc), (int)mask); + sdhci_err_stats_inc(host, CTRL_TIMEOUT); sdhci_dumpregs(host); return; } @@ -1716,6 +1717,7 @@ static bool sdhci_send_command_retry(struct sdhci_host *host, if (!timeout--) { pr_err("%s: Controller never released inhibit bit(s).\n", mmc_hostname(host->mmc)); + sdhci_err_stats_inc(host, CTRL_TIMEOUT); sdhci_dumpregs(host); cmd->error = -EIO; return false; @@ -1965,6 +1967,7 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk) if (timedout) { pr_err("%s: Internal clock never stabilised.\n", mmc_hostname(host->mmc)); + sdhci_err_stats_inc(host, CTRL_TIMEOUT); sdhci_dumpregs(host); return; } @@ -1987,6 +1990,7 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk) if (timedout) { pr_err("%s: PLL clock never stabilised.\n", mmc_hostname(host->mmc)); + sdhci_err_stats_inc(host, CTRL_TIMEOUT); sdhci_dumpregs(host); return; } @@ -3161,6 +3165,7 @@ static void sdhci_timeout_timer(struct timer_list *t) if (host->cmd && !sdhci_data_line_cmd(host->cmd)) { pr_err("%s: Timeout waiting for hardware cmd interrupt.\n", mmc_hostname(host->mmc)); + sdhci_err_stats_inc(host, REQ_TIMEOUT); sdhci_dumpregs(host); host->cmd->error = -ETIMEDOUT; @@ -3183,6 +3188,7 @@ static void sdhci_timeout_data_timer(struct timer_list *t) (host->cmd && sdhci_data_line_cmd(host->cmd))) { pr_err("%s: Timeout waiting for hardware interrupt.\n", mmc_hostname(host->mmc)); + sdhci_err_stats_inc(host, REQ_TIMEOUT); sdhci_dumpregs(host); if (host->data) { @@ -3234,17 +3240,21 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) return; pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n", mmc_hostname(host->mmc), (unsigned)intmask); + sdhci_err_stats_inc(host, UNEXPECTED_IRQ); sdhci_dumpregs(host); return; } if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) { - if (intmask & SDHCI_INT_TIMEOUT) + if (intmask & SDHCI_INT_TIMEOUT) { host->cmd->error = -ETIMEDOUT; - else + sdhci_err_stats_inc(host, CMD_TIMEOUT); + } else { host->cmd->error = -EILSEQ; - + if (!mmc_op_tuning(host->cmd->opcode)) + sdhci_err_stats_inc(host, CMD_CRC); + } /* Treat data command CRC error the same as data CRC error */ if (host->cmd->data && (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == @@ -3266,6 +3276,8 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) -ETIMEDOUT : -EILSEQ; + sdhci_err_stats_inc(host, AUTO_CMD); + if (sdhci_auto_cmd23(host, mrq)) { mrq->sbc->error = err; __sdhci_finish_mrq(host, mrq); @@ -3342,6 +3354,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) if (intmask & SDHCI_INT_DATA_TIMEOUT) { host->data_cmd = NULL; data_cmd->error = -ETIMEDOUT; + sdhci_err_stats_inc(host, CMD_TIMEOUT); __sdhci_finish_mrq(host, data_cmd->mrq); return; } @@ -3370,23 +3383,30 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n", mmc_hostname(host->mmc), (unsigned)intmask); + sdhci_err_stats_inc(host, UNEXPECTED_IRQ); sdhci_dumpregs(host); return; } - if (intmask & SDHCI_INT_DATA_TIMEOUT) + if (intmask & SDHCI_INT_DATA_TIMEOUT) { host->data->error = -ETIMEDOUT; - else if (intmask & SDHCI_INT_DATA_END_BIT) + sdhci_err_stats_inc(host, DAT_TIMEOUT); + } else if (intmask & SDHCI_INT_DATA_END_BIT) { host->data->error = -EILSEQ; - else if ((intmask & SDHCI_INT_DATA_CRC) && + if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) + sdhci_err_stats_inc(host, DAT_CRC); + } else if ((intmask & SDHCI_INT_DATA_CRC) && SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) - != MMC_BUS_TEST_R) + != MMC_BUS_TEST_R) { host->data->error = -EILSEQ; - else if (intmask & SDHCI_INT_ADMA_ERROR) { + if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) + sdhci_err_stats_inc(host, DAT_CRC); + } else if (intmask & SDHCI_INT_ADMA_ERROR) { pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc), intmask); sdhci_adma_show_error(host); + sdhci_err_stats_inc(host, ADMA); host->data->error = -EIO; if (host->ops->adma_workaround) host->ops->adma_workaround(host, intmask); @@ -3584,6 +3604,7 @@ out: if (unexpected) { pr_err("%s: Unexpected interrupt 0x%08x.\n", mmc_hostname(host->mmc), unexpected); + sdhci_err_stats_inc(host, UNEXPECTED_IRQ); sdhci_dumpregs(host); } @@ -3905,20 +3926,27 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, if (!host->cqe_on) return false; - if (intmask & (SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC)) + if (intmask & (SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC)) { *cmd_error = -EILSEQ; - else if (intmask & SDHCI_INT_TIMEOUT) + if (!mmc_op_tuning(host->cmd->opcode)) + sdhci_err_stats_inc(host, CMD_CRC); + } else if (intmask & SDHCI_INT_TIMEOUT) { *cmd_error = -ETIMEDOUT; - else + sdhci_err_stats_inc(host, CMD_TIMEOUT); + } else *cmd_error = 0; - if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) + if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) { *data_error = -EILSEQ; - else if (intmask & SDHCI_INT_DATA_TIMEOUT) + if (!mmc_op_tuning(host->cmd->opcode)) + sdhci_err_stats_inc(host, DAT_CRC); + } else if (intmask & SDHCI_INT_DATA_TIMEOUT) { *data_error = -ETIMEDOUT; - else if (intmask & SDHCI_INT_ADMA_ERROR) + sdhci_err_stats_inc(host, DAT_TIMEOUT); + } else if (intmask & SDHCI_INT_ADMA_ERROR) { *data_error = -EIO; - else + sdhci_err_stats_inc(host, ADMA); + } else *data_error = 0; /* Clear selected interrupts. */ @@ -3934,6 +3962,7 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, sdhci_writel(host, intmask, SDHCI_INT_STATUS); pr_err("%s: CQE: Unexpected interrupt 0x%08x.\n", mmc_hostname(host->mmc), intmask); + sdhci_err_stats_inc(host, UNEXPECTED_IRQ); sdhci_dumpregs(host); } diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index d7929d725730..95a08f09df30 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -356,6 +356,9 @@ struct sdhci_adma2_64_desc { */ #define MMC_CMD_TRANSFER_TIME (10 * NSEC_PER_MSEC) /* max 10 ms */ +#define sdhci_err_stats_inc(host, err_name) \ + mmc_debugfs_err_stats_inc((host)->mmc, MMC_ERR_##err_name) + enum sdhci_cookie { COOKIE_UNMAPPED, COOKIE_PRE_MAPPED, /* mapped by sdhci_pre_req() */ diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index d9a65c6a8816..9c50bc40f8ff 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -99,6 +99,12 @@ static inline bool mmc_op_multi(u32 opcode) opcode == MMC_READ_MULTIPLE_BLOCK; } +static inline bool mmc_op_tuning(u32 opcode) +{ + return opcode == MMC_SEND_TUNING_BLOCK || + opcode == MMC_SEND_TUNING_BLOCK_HS200; +} + /* * MMC_SWITCH argument format: * From 7ae20fa3552a619694c2894b09e19332fe0d007f Mon Sep 17 00:00:00 2001 From: Shaik Sajida Bhanu Date: Fri, 27 May 2022 23:23:54 +0530 Subject: [PATCH 050/111] mmc: debugfs: Add debug fs entry for mmc driver Add debug fs entry to query eMMC and SD card errors statistics Signed-off-by: Liangliang Lu Signed-off-by: Sayali Lokhande Signed-off-by: Bao D. Nguyen Signed-off-by: Shaik Sajida Bhanu Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/1653674036-21829-4-git-send-email-quic_c_sbhanu@quicinc.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/debugfs.c | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 3fdbc801e64a..6aa5a60b6e81 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -223,6 +223,59 @@ static int mmc_clock_opt_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set, "%llu\n"); +static int mmc_err_stats_show(struct seq_file *file, void *data) +{ + struct mmc_host *host = (struct mmc_host *)file->private; + const char *desc[MMC_ERR_MAX] = { + [MMC_ERR_CMD_TIMEOUT] = "Command Timeout Occurred", + [MMC_ERR_CMD_CRC] = "Command CRC Errors Occurred", + [MMC_ERR_DAT_TIMEOUT] = "Data Timeout Occurred", + [MMC_ERR_DAT_CRC] = "Data CRC Errors Occurred", + [MMC_ERR_AUTO_CMD] = "Auto-Cmd Error Occurred", + [MMC_ERR_ADMA] = "ADMA Error Occurred", + [MMC_ERR_TUNING] = "Tuning Error Occurred", + [MMC_ERR_CMDQ_RED] = "CMDQ RED Errors", + [MMC_ERR_CMDQ_GCE] = "CMDQ GCE Errors", + [MMC_ERR_CMDQ_ICCE] = "CMDQ ICCE Errors", + [MMC_ERR_REQ_TIMEOUT] = "Request Timedout", + [MMC_ERR_CMDQ_REQ_TIMEOUT] = "CMDQ Request Timedout", + [MMC_ERR_ICE_CFG] = "ICE Config Errors", + [MMC_ERR_CTRL_TIMEOUT] = "Controller Timedout errors", + [MMC_ERR_UNEXPECTED_IRQ] = "Unexpected IRQ errors", + }; + int i; + + for (i = 0; i < MMC_ERR_MAX; i++) { + if (desc[i]) + seq_printf(file, "# %s:\t %d\n", + desc[i], host->err_stats[i]); + } + + return 0; +} + +static int mmc_err_stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, mmc_err_stats_show, inode->i_private); +} + +static ssize_t mmc_err_stats_write(struct file *filp, const char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + struct mmc_host *host = filp->f_mapping->host->i_private; + + pr_debug("%s: Resetting MMC error statistics\n", __func__); + memset(host->err_stats, 0, sizeof(host->err_stats)); + + return cnt; +} + +static const struct file_operations mmc_err_stats_fops = { + .open = mmc_err_stats_open, + .read = seq_read, + .write = mmc_err_stats_write, +}; + void mmc_add_host_debugfs(struct mmc_host *host) { struct dentry *root; @@ -236,6 +289,9 @@ void mmc_add_host_debugfs(struct mmc_host *host) debugfs_create_file_unsafe("clock", S_IRUSR | S_IWUSR, root, host, &mmc_clock_fops); + debugfs_create_file("err_stats", 0600, root, host, + &mmc_err_stats_fops); + #ifdef CONFIG_FAIL_MMC_REQUEST if (fail_request) setup_fault_attr(&fail_default_attr, fail_request); From fadf344e6d69a94efa17619120132516f56b582c Mon Sep 17 00:00:00 2001 From: Shaik Sajida Bhanu Date: Fri, 27 May 2022 23:23:55 +0530 Subject: [PATCH 051/111] mmc: debugfs: Add debug fs error state entry for mmc driver Add debug fs entry error state to query eMMC and SD card errors statistics. If any errors occurred in eMMC and SD card driver level then err_state value will be set to 1. Signed-off-by: Liangliang Lu Signed-off-by: Sayali Lokhande Signed-off-by: Bao D. Nguyen Signed-off-by: Shaik Sajida Bhanu Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/1653674036-21829-5-git-send-email-quic_c_sbhanu@quicinc.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/debugfs.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 6aa5a60b6e81..75e98ec88fb9 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -223,6 +223,27 @@ static int mmc_clock_opt_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(mmc_clock_fops, mmc_clock_opt_get, mmc_clock_opt_set, "%llu\n"); +static int mmc_err_state_get(void *data, u64 *val) +{ + struct mmc_host *host = data; + int i; + + if (!host) + return -EINVAL; + + *val = 0; + for (i = 0; i < MMC_ERR_MAX; i++) { + if (host->err_stats[i]) { + *val = 1; + break; + } + } + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(mmc_err_state, mmc_err_state_get, NULL, "%llu\n"); + static int mmc_err_stats_show(struct seq_file *file, void *data) { struct mmc_host *host = (struct mmc_host *)file->private; @@ -289,6 +310,8 @@ void mmc_add_host_debugfs(struct mmc_host *host) debugfs_create_file_unsafe("clock", S_IRUSR | S_IWUSR, root, host, &mmc_clock_fops); + debugfs_create_file_unsafe("err_state", 0600, root, host, + &mmc_err_state); debugfs_create_file("err_stats", 0600, root, host, &mmc_err_stats_fops); From e5f7a3c64c0151da7080bebbe2940f00c3a4162e Mon Sep 17 00:00:00 2001 From: Shaik Sajida Bhanu Date: Fri, 27 May 2022 23:23:56 +0530 Subject: [PATCH 052/111] mmc: cqhci: Capture eMMC and SD card errors Add changes to capture eMMC and SD card errors. This is useful for debug and testing. Signed-off-by: Liangliang Lu Signed-off-by: Sayali Lokhande Signed-off-by: Bao D. Nguyen Signed-off-by: Ram Prakash Gupta Signed-off-by: Shaik Sajida Bhanu Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/1653674036-21829-6-git-send-email-quic_c_sbhanu@quicinc.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/cqhci-core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/cqhci-core.c b/drivers/mmc/host/cqhci-core.c index b0d30c35c390..b3d7d6d8d654 100644 --- a/drivers/mmc/host/cqhci-core.c +++ b/drivers/mmc/host/cqhci-core.c @@ -822,8 +822,15 @@ irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error, pr_debug("%s: cqhci: IRQ status: 0x%08x\n", mmc_hostname(mmc), status); if ((status & (CQHCI_IS_RED | CQHCI_IS_GCE | CQHCI_IS_ICCE)) || - cmd_error || data_error) + cmd_error || data_error) { + if (status & CQHCI_IS_RED) + mmc_debugfs_err_stats_inc(mmc, MMC_ERR_CMDQ_RED); + if (status & CQHCI_IS_GCE) + mmc_debugfs_err_stats_inc(mmc, MMC_ERR_CMDQ_GCE); + if (status & CQHCI_IS_ICCE) + mmc_debugfs_err_stats_inc(mmc, MMC_ERR_CMDQ_ICCE); cqhci_error_irq(mmc, status, cmd_error, data_error); + } if (status & CQHCI_IS_TCC) { /* read TCN and complete the request */ From 354c6d33ddfbda5b29063ffff54a965301e2e459 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 5 Jun 2022 18:37:09 +0200 Subject: [PATCH 053/111] dt-bindings: mmc: samsung,exynos-dw-mshc: convert to dtschema Convert the Samsung Exynos SoC specific extensions to the Synopsys Designware Mobile Storage Host Controller to DT schema. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20220605163710.144210-4-krzysztof.kozlowski@linaro.org Signed-off-by: Ulf Hansson --- .../bindings/mmc/exynos-dw-mshc.txt | 94 ----------- .../bindings/mmc/samsung,exynos-dw-mshc.yaml | 159 ++++++++++++++++++ 2 files changed, 159 insertions(+), 94 deletions(-) delete mode 100644 Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt create mode 100644 Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt deleted file mode 100644 index 753e9d7d8956..000000000000 --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt +++ /dev/null @@ -1,94 +0,0 @@ -* Samsung Exynos specific extensions to the Synopsys Designware Mobile - Storage Host Controller - -The Synopsys designware mobile storage host controller is used to interface -a SoC with storage medium such as eMMC or SD/MMC cards. This file documents -differences between the core Synopsys dw mshc controller properties described -by synopsys-dw-mshc.txt and the properties used by the Samsung Exynos specific -extensions to the Synopsys Designware Mobile Storage Host Controller. - -Required Properties: - -* compatible: should be - - "samsung,exynos4210-dw-mshc": for controllers with Samsung Exynos4210 - specific extensions. - - "samsung,exynos4412-dw-mshc": for controllers with Samsung Exynos4412 - specific extensions. - - "samsung,exynos5250-dw-mshc": for controllers with Samsung Exynos5250 - specific extensions. - - "samsung,exynos5420-dw-mshc": for controllers with Samsung Exynos5420 - specific extensions. - - "samsung,exynos7-dw-mshc": for controllers with Samsung Exynos7 - specific extensions. - - "samsung,exynos7-dw-mshc-smu": for controllers with Samsung Exynos7 - specific extensions having an SMU. - - "axis,artpec8-dw-mshc": for controllers with ARTPEC-8 specific - extensions. - -* samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface - unit (ciu) clock. This property is applicable only for Exynos5 SoC's and - ignored for Exynos4 SoC's. The valid range of divider value is 0 to 7. - -* samsung,dw-mshc-sdr-timing: Specifies the value of CIU clock phase shift value - in transmit mode and CIU clock phase shift value in receive mode for single - data rate mode operation. Refer notes below for the order of the cells and the - valid values. - -* samsung,dw-mshc-ddr-timing: Specifies the value of CUI clock phase shift value - in transmit mode and CIU clock phase shift value in receive mode for double - data rate mode operation. Refer notes below for the order of the cells and the - valid values. -* samsung,dw-mshc-hs400-timing: Specifies the value of CIU TX and RX clock phase - shift value for hs400 mode operation. - - Notes for the sdr-timing and ddr-timing values: - - The order of the cells should be - - First Cell: CIU clock phase shift value for tx mode. - - Second Cell: CIU clock phase shift value for rx mode. - - Valid values for SDR and DDR CIU clock timing for Exynos5250: - - valid value for tx phase shift and rx phase shift is 0 to 7. - - when CIU clock divider value is set to 3, all possible 8 phase shift - values can be used. - - if CIU clock divider value is 0 (that is divide by 1), both tx and rx - phase shift clocks should be 0. - -* samsung,read-strobe-delay: RCLK (Data strobe) delay to control HS400 mode - (Latency value for delay line in Read path) - -Required properties for a slot (Deprecated - Recommend to use one slot per host): - -* gpios: specifies a list of gpios used for command, clock and data bus. The - first gpio is the command line and the second gpio is the clock line. The - rest of the gpios (depending on the bus-width property) are the data lines in - no particular order. The format of the gpio specifier depends on the gpio - controller. -(Deprecated - Refer to Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt) - -Example: - - The MSHC controller node can be split into two portions, SoC specific and - board specific portions as listed below. - - dwmmc0@12200000 { - compatible = "samsung,exynos5250-dw-mshc"; - reg = <0x12200000 0x1000>; - interrupts = <0 75 0>; - #address-cells = <1>; - #size-cells = <0>; - }; - - dwmmc0@12200000 { - cap-mmc-highspeed; - cap-sd-highspeed; - broken-cd; - fifo-depth = <0x80>; - card-detect-delay = <200>; - samsung,dw-mshc-ciu-div = <3>; - samsung,dw-mshc-sdr-timing = <2 3>; - samsung,dw-mshc-ddr-timing = <1 2>; - samsung,dw-mshc-hs400-timing = <0 2>; - samsung,read-strobe-delay = <90>; - bus-width = <8>; - }; diff --git a/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml new file mode 100644 index 000000000000..80c557e938a2 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml @@ -0,0 +1,159 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/samsung,exynos-dw-mshc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: + Samsung Exynos SoC specific extensions to the Synopsys Designware Mobile + Storage Host Controller + +maintainers: + - Jaehoon Chung + - Krzysztof Kozlowski + +properties: + compatible: + enum: + - samsung,exynos4210-dw-mshc + - samsung,exynos4412-dw-mshc + - samsung,exynos5250-dw-mshc + - samsung,exynos5420-dw-mshc + - samsung,exynos7-dw-mshc + - samsung,exynos7-dw-mshc-smu + - axis,artpec8-dw-mshc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 2 + description: + Handle to "biu" and "ciu" clocks for the + bus interface unit clock and the card interface unit clock. + + clock-names: + items: + - const: biu + - const: ciu + + samsung,dw-mshc-ciu-div: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 7 + description: + The divider value for the card interface unit (ciu) clock. + + samsung,dw-mshc-ddr-timing: + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + - description: CIU clock phase shift value for tx mode + minimum: 0 + maximum: 7 + - description: CIU clock phase shift value for rx mode + minimum: 0 + maximum: 7 + description: + The value of CUI clock phase shift value in transmit mode and CIU clock + phase shift value in receive mode for double data rate mode operation. + See also samsung,dw-mshc-hs400-timing property. + + samsung,dw-mshc-hs400-timing: + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + - description: CIU clock phase shift value for tx mode + minimum: 0 + maximum: 7 + - description: CIU clock phase shift value for rx mode + minimum: 0 + maximum: 7 + description: | + The value of CIU TX and RX clock phase shift value for HS400 mode + operation. + Valid values for SDR and DDR CIU clock timing:: + - valid value for tx phase shift and rx phase shift is 0 to 7. + - when CIU clock divider value is set to 3, all possible 8 phase shift + values can be used. + - if CIU clock divider value is 0 (that is divide by 1), both tx and rx + phase shift clocks should be 0. + If missing, values from samsung,dw-mshc-ddr-timing property are used. + + samsung,dw-mshc-sdr-timing: + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + - description: CIU clock phase shift value for tx mode + minimum: 0 + maximum: 7 + - description: CIU clock phase shift value for rx mode + minimum: 0 + maximum: 7 + description: + The value of CIU clock phase shift value in transmit mode and CIU clock + phase shift value in receive mode for single data rate mode operation. + See also samsung,dw-mshc-hs400-timing property. + + samsung,read-strobe-delay: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + RCLK (Data strobe) delay to control HS400 mode (Latency value for delay + line in Read path). If missing, default from hardware is used. + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - samsung,dw-mshc-ddr-timing + - samsung,dw-mshc-sdr-timing + +allOf: + - $ref: "synopsys-dw-mshc-common.yaml#" + - if: + properties: + compatible: + contains: + enum: + - samsung,exynos5250-dw-mshc + - samsung,exynos5420-dw-mshc + - samsung,exynos7-dw-mshc + - samsung,exynos7-dw-mshc-smu + - axis,artpec8-dw-mshc + then: + required: + - samsung,dw-mshc-ciu-div + +unevaluatedProperties: false + +examples: + - | + #include + #include + + mmc@12220000 { + compatible = "samsung,exynos5420-dw-mshc"; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x12220000 0x1000>; + clocks = <&clock CLK_MMC2>, <&clock CLK_SCLK_MMC2>; + clock-names = "biu", "ciu"; + fifo-depth = <0x40>; + card-detect-delay = <200>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <0 4>; + samsung,dw-mshc-ddr-timing = <0 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_wp &sd2_bus1 &sd2_bus4>; + bus-width = <4>; + cap-sd-highspeed; + max-frequency = <200000000>; + vmmc-supply = <&ldo19_reg>; + vqmmc-supply = <&ldo13_reg>; + sd-uhs-sdr50; + sd-uhs-sdr104; + sd-uhs-ddr50; + }; From ca812a4e8f7c438edb817b618fb38ceffdd9c04c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 5 Jun 2022 18:37:10 +0200 Subject: [PATCH 054/111] dt-bindings: mmc: samsung,exynos-dw-mshc: document Exynos5420 SMU Document the compatible for Samsung Exynos5420 SoC Synopsys Designware MSHC with SMU, already used in DTS and driver. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20220605163710.144210-5-krzysztof.kozlowski@linaro.org Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml index 80c557e938a2..fdaa18481aa0 100644 --- a/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml +++ b/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml @@ -19,6 +19,7 @@ properties: - samsung,exynos4412-dw-mshc - samsung,exynos5250-dw-mshc - samsung,exynos5420-dw-mshc + - samsung,exynos5420-dw-mshc-smu - samsung,exynos7-dw-mshc - samsung,exynos7-dw-mshc-smu - axis,artpec8-dw-mshc From ffe18c0f7ced226ac07a4079ed504312418bfb6c Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Mon, 6 Jun 2022 21:13:41 +0100 Subject: [PATCH 055/111] dt-bindings: mmc: convert mmc-spi-slot to yaml Convert the mmc-spi-slot text based binding doc to yaml, with the side effect of cleaning up some of the riscv dtbs_check warnings. Reviewed-by: Rob Herring Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20220606201343.514391-2-mail@conchuod.ie Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/mmc-spi-slot.txt | 29 ------- .../devicetree/bindings/mmc/mmc-spi-slot.yaml | 77 +++++++++++++++++++ 2 files changed, 77 insertions(+), 29 deletions(-) delete mode 100644 Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt create mode 100644 Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml diff --git a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt deleted file mode 100644 index 5e74db69f581..000000000000 --- a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt +++ /dev/null @@ -1,29 +0,0 @@ -MMC/SD/SDIO slot directly connected to a SPI bus - -This file documents differences between the core properties described -by mmc.txt and the properties used by the mmc_spi driver. - -Required properties: -- spi-max-frequency : maximum frequency for this device (Hz). - -Optional properties: -- voltage-ranges : two cells are required, first cell specifies minimum - slot voltage (mV), second cell specifies maximum slot voltage (mV). - Several ranges could be specified. If not provided, 3.2v..3.4v is assumed. -- gpios : may specify GPIOs in this order: Card-Detect GPIO, - Write-Protect GPIO. Note that this does not follow the - binding from mmc.txt, for historical reasons. - -Example: - - mmc-slot@0 { - compatible = "fsl,mpc8323rdb-mmc-slot", - "mmc-spi-slot"; - reg = <0>; - gpios = <&qe_pio_d 14 1 - &qe_pio_d 15 0>; - voltage-ranges = <3300 3300>; - spi-max-frequency = <50000000>; - interrupts = <42>; - interrupt-parent = <&PIC>; - }; diff --git a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml new file mode 100644 index 000000000000..c45b91099325 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/mmc-spi-slot.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MMC/SD/SDIO slot directly connected to a SPI bus + +maintainers: + - Ulf Hansson + +allOf: + - $ref: "mmc-controller.yaml" + - $ref: /schemas/spi/spi-peripheral-props.yaml + +description: | + The extra properties used by an mmc connected via SPI. + +properties: + compatible: + const: mmc-spi-slot + + reg: + maxItems: 1 + + spi-max-frequency: true + + interrupts: + maxItems: 1 + + voltage-ranges: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: | + Two cells are required, first cell specifies minimum slot voltage (mV), + second cell specifies maximum slot voltage (mV). + items: + - description: | + value for minimum slot voltage in mV + default: 3200 + - description: | + value for maximum slot voltage in mV + default: 3400 + + gpios: + description: | + For historical reasons, this does not follow the generic mmc-controller + binding. + minItems: 1 + items: + - description: Card-Detect GPIO + - description: Write-Protect GPIO + +required: + - compatible + - reg + - spi-max-frequency + +unevaluatedProperties: false + +examples: + - | + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + mmc@0 { + compatible = "mmc-spi-slot"; + reg = <0>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>, <&gpio 15 GPIO_ACTIVE_HIGH>; + voltage-ranges = <3300 3300>; + spi-max-frequency = <50000000>; + interrupts = <42>; + interrupt-parent = <&PIC>; + }; + }; + +... From 7b651cc6de2470e112b3e792ba2e7775e1127c04 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 4 Jun 2022 01:33:00 +0200 Subject: [PATCH 056/111] mmc: renesas_sdhi: add R-Car Gen4 fallback compatibility string For now, Gen4 is treated the same as Gen3. But we still want a seperate fallback just in case. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20220603233300.21789-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 3084b15ae2cb..8f2e6619fa68 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -268,6 +268,7 @@ static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = { { .compatible = "renesas,sdhi-r8a77990", .data = &of_r8a77990_compatible, }, { .compatible = "renesas,sdhi-r8a77995", .data = &of_rcar_gen3_nohs400_compatible, }, { .compatible = "renesas,rcar-gen3-sdhi", .data = &of_rcar_gen3_compatible, }, + { .compatible = "renesas,rcar-gen4-sdhi", .data = &of_rcar_gen3_compatible, }, {}, }; MODULE_DEVICE_TABLE(of, renesas_sdhi_internal_dmac_of_match); From 3576c0b2709c8204a18371d5f8b44a724234ffe7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 4 Jun 2022 01:38:10 +0200 Subject: [PATCH 057/111] dt-bindings: mmc: renesas,sdhi: Document R-Car S4-8 and generic Gen4 support Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20220603233810.21972-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml index 9ac4986988c5..b46a90eb2063 100644 --- a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml +++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml @@ -61,6 +61,10 @@ properties: - renesas,sdhi-r9a07g044 # RZ/G2{L,LC} - renesas,sdhi-r9a07g054 # RZ/V2L - const: renesas,rcar-gen3-sdhi # R-Car Gen3 or RZ/G2 + - items: + - enum: + - renesas,sdhi-r8a779f0 # R-Car S4-8 + - const: renesas,rcar-gen4-sdhi # R-Car Gen4 reg: maxItems: 1 From ba1de43768aa27865169af00ee0c2a4a165690b6 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 8 Jun 2022 09:01:52 +0000 Subject: [PATCH 058/111] mmc: debugfs: Fix file release memory leak When using single_open() for opening, single_release() should be used instead of seq_release(), otherwise there is a memory leak. Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20220608090152.179395-1-weiyongjun1@huawei.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/debugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 75e98ec88fb9..fe6808771bc7 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -295,6 +295,7 @@ static const struct file_operations mmc_err_stats_fops = { .open = mmc_err_stats_open, .read = seq_read, .write = mmc_err_stats_write, + .release = single_release, }; void mmc_add_host_debugfs(struct mmc_host *host) From cae45c2d4fb3a9084954f14bf991500c49c970c9 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 8 Jun 2022 11:48:31 +0200 Subject: [PATCH 059/111] dt-bindings: mmc: renesas,sdhi: R-Car V3U is R-Car Gen4 Despite the name, R-Car V3U is the first member of the R-Car Gen4 family. Hence move its compatible value to the R-Car Gen4 section. Signed-off-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20220608094831.8242-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml index b46a90eb2063..d5b29728704b 100644 --- a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml +++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml @@ -56,13 +56,13 @@ properties: - renesas,sdhi-r8a77980 # R-Car V3H - renesas,sdhi-r8a77990 # R-Car E3 - renesas,sdhi-r8a77995 # R-Car D3 - - renesas,sdhi-r8a779a0 # R-Car V3U - renesas,sdhi-r9a07g043 # RZ/G2UL - renesas,sdhi-r9a07g044 # RZ/G2{L,LC} - renesas,sdhi-r9a07g054 # RZ/V2L - const: renesas,rcar-gen3-sdhi # R-Car Gen3 or RZ/G2 - items: - enum: + - renesas,sdhi-r8a779a0 # R-Car V3U - renesas,sdhi-r8a779f0 # R-Car S4-8 - const: renesas,rcar-gen4-sdhi # R-Car Gen4 From 0f6fe934a628b0ce0ba138697064fbc8802c21b1 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 8 Jun 2022 14:23:44 +0200 Subject: [PATCH 060/111] dt-bindings: mmc: renesas,sdhi: Add R-Car Gen4 clock requirements The patch enabling generic Gen4 support forgot to add the clock requirements which are the same as for Gen3. Update the binding. Reported-by: Geert Uytterhoeven Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20220608122344.3431-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml index d5b29728704b..14945ebc31d2 100644 --- a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml +++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml @@ -145,6 +145,7 @@ allOf: enum: - renesas,rcar-gen2-sdhi - renesas,rcar-gen3-sdhi + - renesas,rcar-gen4-sdhi then: properties: clocks: From f78bc9f2caa4e37fafa623faa8f5c683b4c4b35e Mon Sep 17 00:00:00 2001 From: Xiang wangx Date: Wed, 8 Jun 2022 21:08:47 +0800 Subject: [PATCH 061/111] mmc: mmci: Fix typo in comment Delete the redundant word 'is'. Signed-off-by: Xiang wangx Link: https://lore.kernel.org/r/20220608130847.46359-1-wangxiang@cdjrlc.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mmci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 01159eaf8694..012aa85489d8 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -762,7 +762,7 @@ int mmci_dmae_setup(struct mmci_host *host) /* * If only an RX channel is specified, the driver will - * attempt to use it bidirectionally, however if it is + * attempt to use it bidirectionally, however if it * is specified but cannot be located, DMA will be disabled. */ if (dmae->rx_channel && !dmae->tx_channel) From c3c0ed75ffbff5c70667030b5139bbb75b0a30f5 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Wed, 8 Jun 2022 08:27:57 -0700 Subject: [PATCH 062/111] mmc: sdhci-brcmstb: Initialize base_clk to NULL in sdhci_brcmstb_probe() Clang warns a few times along the lines of: drivers/mmc/host/sdhci-brcmstb.c:302:6: warning: variable 'base_clk' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized] if (res) ^~~ drivers/mmc/host/sdhci-brcmstb.c:376:24: note: uninitialized use occurs here clk_disable_unprepare(base_clk); ^~~~~~~~ base_clk is used in the error path before it is initialized. Initialize it to NULL, as clk_disable_unprepare() calls clk_disable() and clk_unprepare(), which both handle NULL pointers gracefully. Link: https://github.com/ClangBuiltLinux/linux/issues/1650 Reported-by: kernel test robot Signed-off-by: Nathan Chancellor Acked-by: Florian Fainelli Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20220608152757.82529-1-nathan@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-brcmstb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index f8dff8537920..28e9cf995c41 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -256,7 +256,7 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) struct sdhci_host *host; struct resource *iomem; struct clk *clk; - struct clk *base_clk; + struct clk *base_clk = NULL; int res; match = of_match_node(sdhci_brcm_of_match, pdev->dev.of_node); From 68eab5176c71fe03ff37723a1c5cf20c26b06a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 10 Jun 2022 23:12:53 +0200 Subject: [PATCH 063/111] mmc: dw_mmc: exynos: Obviously always return success in remove callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dw_mci_pltfm_remove() returns 0 unconditionally and returning an error in a platform remove callback isn't very sensible. (The only effect of the latter is that the device core emits a generic warning and then removes the device anyhow.) So return 0 unconditionally to make it obvious there is no error forwarded to the upper layers. This is a preparation for making platform remove callbacks return void. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20220610211257.102071-1-u.kleine-koenig@pengutronix.de Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc-exynos.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index ca5be4445ae0..9f20ac524c8b 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -670,7 +670,9 @@ static int dw_mci_exynos_remove(struct platform_device *pdev) pm_runtime_set_suspended(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - return dw_mci_pltfm_remove(pdev); + dw_mci_pltfm_remove(pdev); + + return 0; } static const struct dev_pm_ops dw_mci_exynos_pmops = { From 50699358222d004ad2b465c18b03d418b9b7fa90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 10 Jun 2022 23:12:54 +0200 Subject: [PATCH 064/111] mmc: dw_mmc: hi3789cv200: Obviously always return success in remove callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dw_mci_pltfm_remove() returns 0 unconditionally and returning an error in a platform remove callback isn't very sensible. (The only effect of the latter is that the device core emits a generic warning and then removes the device anyhow.) So return 0 unconditionally to make it obvious there is no error forwarded to the upper layers. This is a preparation for making platform remove callbacks return void. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20220610211257.102071-2-u.kleine-koenig@pengutronix.de Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc-hi3798cv200.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc-hi3798cv200.c b/drivers/mmc/host/dw_mmc-hi3798cv200.c index e9437ef8ef19..6f22fe054087 100644 --- a/drivers/mmc/host/dw_mmc-hi3798cv200.c +++ b/drivers/mmc/host/dw_mmc-hi3798cv200.c @@ -179,7 +179,9 @@ static int dw_mci_hi3798cv200_remove(struct platform_device *pdev) clk_disable_unprepare(priv->drive_clk); clk_disable_unprepare(priv->sample_clk); - return dw_mci_pltfm_remove(pdev); + dw_mci_pltfm_remove(pdev); + + return 0; } static const struct of_device_id dw_mci_hi3798cv200_match[] = { From 397605c2d02abdcaba00e830fee0ee70a88b9456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 10 Jun 2022 23:12:55 +0200 Subject: [PATCH 065/111] mmc: dw_mmc: rockchip: Obviously always return success in remove callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dw_mci_pltfm_remove() returns 0 unconditionally and returning an error in a platform remove callback isn't very sensible. (The only effect of the latter is that the device core emits a generic warning and then removes the device anyhow.) So return 0 unconditionally to make it obvious there is no error forwarded to the upper layers. This is a preparation for making platform remove callbacks return void. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20220610211257.102071-3-u.kleine-koenig@pengutronix.de Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc-rockchip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index f825487aa739..2a99f15f527f 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c @@ -377,7 +377,9 @@ static int dw_mci_rockchip_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - return dw_mci_pltfm_remove(pdev); + dw_mci_pltfm_remove(pdev); + + return 0; } static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = { From 869f98756e55dbf4ec30e104f6ea1432e8f0bc19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 10 Jun 2022 23:12:56 +0200 Subject: [PATCH 066/111] mmc: sdhci-of-arasan: Obviously always return success in remove callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sdhci_pltfm_unregister() returns 0 unconditionally and returning an error in a platform remove callback isn't very sensible. (The only effect of the latter is that the device core emits a generic warning and then removes the device anyhow.) So return 0 unconditionally to make it obvious there is no error forwarded to the upper layers. This is a preparation for making platform remove callbacks return void. Signed-off-by: Uwe Kleine-König Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20220610211257.102071-4-u.kleine-koenig@pengutronix.de Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-arasan.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 757801dfc308..3997cad1f793 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -1733,7 +1733,6 @@ err_pltfm_free: static int sdhci_arasan_remove(struct platform_device *pdev) { - int ret; struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); @@ -1747,11 +1746,11 @@ static int sdhci_arasan_remove(struct platform_device *pdev) sdhci_arasan_unregister_sdclk(&pdev->dev); - ret = sdhci_pltfm_unregister(pdev); + sdhci_pltfm_unregister(pdev); clk_disable_unprepare(clk_ahb); - return ret; + return 0; } static struct platform_driver sdhci_arasan_driver = { From f6c3397dc67f8141f1a7931e891732351a27d3e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 10 Jun 2022 23:12:57 +0200 Subject: [PATCH 067/111] mmc: sdhci-st: Obviously always return success in remove callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sdhci_pltfm_unregister() returns 0 unconditionally and returning an error in a platform remove callback isn't very sensible. (The only effect of the latter is that the device core emits a generic warning and then removes the device anyhow.) So return 0 unconditionally to make it obvious there is no error forwarded to the upper layers. This is a preparation for making platform remove callbacks return void. Signed-off-by: Uwe Kleine-König Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20220610211257.102071-5-u.kleine-koenig@pengutronix.de Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-st.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index d41582c21aa3..6415916fbd91 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -440,15 +440,14 @@ static int sdhci_st_remove(struct platform_device *pdev) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); struct reset_control *rstc = pdata->rstc; - int ret; - ret = sdhci_pltfm_unregister(pdev); + sdhci_pltfm_unregister(pdev); clk_disable_unprepare(pdata->icnclk); reset_control_assert(rstc); - return ret; + return 0; } #ifdef CONFIG_PM_SLEEP From f9e5b33934cec24b8c024add5c5d65d2f93ade05 Mon Sep 17 00:00:00 2001 From: Jason Lai Date: Mon, 13 Jun 2022 17:29:07 +0800 Subject: [PATCH 068/111] mmc: host: Improve I/O read/write performance for GL9763E Due to flaws in hardware design, GL9763E takes long time to exit from L1 state. The I/O performance will suffer severe impact if it often enter and exit L1 state during I/O requests. To improve I/O read/write performance and take battery life into account, let's turn on GL9763E L1 negotiation before entering runtime suspend and turn off GL9763E L1 negotiation while executing runtime resume. That is to say, GL9763E will not enter L1 state when executing I/O requests and enter L1 state when PCIe bus idle. Signed-off-by: Renius Chen Signed-off-by: Jason Lai Link: https://lore.kernel.org/r/20220613092907.2502-1-jason.lai@genesyslogic.com.tw [Ulf: Improved the commit message a bit] Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-gli.c | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index f13c08db3da5..a76506adc206 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -95,6 +95,9 @@ #define PCIE_GLI_9763E_SCR 0x8E0 #define GLI_9763E_SCR_AXI_REQ BIT(9) +#define PCIE_GLI_9763E_CFG 0x8A0 +#define GLI_9763E_CFG_LPSN_DIS BIT(12) + #define PCIE_GLI_9763E_CFG2 0x8A4 #define GLI_9763E_CFG2_L1DLY GENMASK(28, 19) #define GLI_9763E_CFG2_L1DLY_MID 0x54 @@ -828,6 +831,31 @@ static void sdhci_gl9763e_dumpregs(struct mmc_host *mmc) sdhci_dumpregs(mmc_priv(mmc)); } +static void gl9763e_set_low_power_negotiation(struct sdhci_pci_slot *slot, bool enable) +{ + struct pci_dev *pdev = slot->chip->pdev; + u32 value; + + pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); + value &= ~GLI_9763E_VHS_REV; + value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); + pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); + + pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG, &value); + + if (enable) + value &= ~GLI_9763E_CFG_LPSN_DIS; + else + value |= GLI_9763E_CFG_LPSN_DIS; + + pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG, value); + + pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); + value &= ~GLI_9763E_VHS_REV; + value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); + pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); +} + static void sdhci_gl9763e_cqe_pre_enable(struct mmc_host *mmc) { struct cqhci_host *cq_host = mmc->cqe_private; @@ -969,6 +997,9 @@ static int gl9763e_runtime_suspend(struct sdhci_pci_chip *chip) struct sdhci_host *host = slot->host; u16 clock; + /* Enable LPM negotiation to allow entering L1 state */ + gl9763e_set_low_power_negotiation(slot, true); + clock = sdhci_readw(host, SDHCI_CLOCK_CONTROL); clock &= ~(SDHCI_CLOCK_PLL_EN | SDHCI_CLOCK_CARD_EN); sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL); @@ -1002,6 +1033,9 @@ static int gl9763e_runtime_resume(struct sdhci_pci_chip *chip) clock |= SDHCI_CLOCK_CARD_EN; sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL); + /* Disable LPM negotiation to avoid entering L1 state. */ + gl9763e_set_low_power_negotiation(slot, false); + return 0; } #endif From 6f34a4ee738b6965a08ba11a03666e7b524aec19 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Tue, 14 Jun 2022 13:39:05 +0200 Subject: [PATCH 069/111] mmc: core: Do not evaluate HS400 capabilities if bus has no MMC capability If 'no-mmc' is set but 'no-mmc-hs400' is not, this warning is raised. Specifying 'no-mmc' should be enough though. Signed-off-by: Alexander Stein Link: https://lore.kernel.org/r/20220614113905.1458715-1-alexander.stein@ew.tq-group.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 2ed2b4d5e5a5..0fd91f749b3a 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -599,7 +599,7 @@ static int mmc_validate_host_caps(struct mmc_host *host) } if (caps2 & (MMC_CAP2_HS400_ES | MMC_CAP2_HS400) && - !(caps & MMC_CAP_8_BIT_DATA)) { + !(caps & MMC_CAP_8_BIT_DATA) && !(caps2 & MMC_CAP2_NO_MMC)) { dev_warn(dev, "drop HS400 support since no 8-bit bus\n"); host->caps2 = caps2 & ~MMC_CAP2_HS400_ES & ~MMC_CAP2_HS400; } From 1c5fd97373115b932afa72fbc5425560e0d1148f Mon Sep 17 00:00:00 2001 From: Ren Zhijie Date: Sun, 19 Jun 2022 18:47:12 +0800 Subject: [PATCH 070/111] mmc: sdhci-pci-gli: Fix build error unused-function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_PM is not set. make ARCH=x86_64 CROSS_COMPILE=x86_64-linux-gnu-, will be failed, like this: drivers/mmc/host/sdhci-pci-gli.c:834:13: error: ‘gl9763e_set_low_power_negotiation’ defined but not used [-Werror=unused-function] static void gl9763e_set_low_power_negotiation(struct sdhci_pci_slot *slot, bool enable) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors make[3]: *** [drivers/mmc/host/sdhci-pci-gli.o] Error 1 To fix building warning, wrap all related code with CONFIG_PM. Reported-by: Hulk Robot Signed-off-by: Ren Zhijie Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20220619104712.125364-1-renzhijie2@huawei.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-gli.c | 50 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index a76506adc206..4d509f656188 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -831,31 +831,6 @@ static void sdhci_gl9763e_dumpregs(struct mmc_host *mmc) sdhci_dumpregs(mmc_priv(mmc)); } -static void gl9763e_set_low_power_negotiation(struct sdhci_pci_slot *slot, bool enable) -{ - struct pci_dev *pdev = slot->chip->pdev; - u32 value; - - pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); - value &= ~GLI_9763E_VHS_REV; - value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); - pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); - - pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG, &value); - - if (enable) - value &= ~GLI_9763E_CFG_LPSN_DIS; - else - value |= GLI_9763E_CFG_LPSN_DIS; - - pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG, value); - - pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); - value &= ~GLI_9763E_VHS_REV; - value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); - pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); -} - static void sdhci_gl9763e_cqe_pre_enable(struct mmc_host *mmc) { struct cqhci_host *cq_host = mmc->cqe_private; @@ -991,6 +966,31 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot) } #ifdef CONFIG_PM +static void gl9763e_set_low_power_negotiation(struct sdhci_pci_slot *slot, bool enable) +{ + struct pci_dev *pdev = slot->chip->pdev; + u32 value; + + pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); + value &= ~GLI_9763E_VHS_REV; + value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); + pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); + + pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG, &value); + + if (enable) + value &= ~GLI_9763E_CFG_LPSN_DIS; + else + value |= GLI_9763E_CFG_LPSN_DIS; + + pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG, value); + + pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); + value &= ~GLI_9763E_VHS_REV; + value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); + pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); +} + static int gl9763e_runtime_suspend(struct sdhci_pci_chip *chip) { struct sdhci_pci_slot *slot = chip->slots[0]; From 39c86b5c59a414cf2a94dbd6956a9a8e70188673 Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 21 Jun 2022 14:52:59 +0800 Subject: [PATCH 071/111] mmc: sdhci-of-esdhc: Fixup use of of_find_compatible_node() Callers of of_find_compatible_node() should drop the reference count accordingly, so let's do that. Signed-off-by: Liang He Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20220621065259.4079817-1-windhl@126.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-esdhc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 8b3d8119f388..e0266638381d 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -1419,7 +1419,7 @@ static int esdhc_hs400_prepare_ddr(struct mmc_host *mmc) static int sdhci_esdhc_probe(struct platform_device *pdev) { struct sdhci_host *host; - struct device_node *np; + struct device_node *np, *tp; struct sdhci_pltfm_host *pltfm_host; struct sdhci_esdhc *esdhc; int ret; @@ -1464,7 +1464,9 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) if (esdhc->vendor_ver > VENDOR_V_22) host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; - if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) { + tp = of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc"); + if (tp) { + of_node_put(tp); host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST; host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; } From 0dac1e498f8130fdacfdd5289e3a7ac87ec1b9ad Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Jun 2022 19:14:37 +0100 Subject: [PATCH 072/111] mmc: renesas_sdhi: Get the reset handle early in the probe In case of devm_reset_control_get_optional_exclusive() failure we returned directly instead of jumping to the error path to roll back initialization. This patch moves devm_reset_control_get_optional_exclusive() early in the probe so that we have the reset handle prior to initialization of the hardware. Fixes: b4d86f37eacb7 ("mmc: renesas_sdhi: do hard reset if possible") Reported-by: Pavel Machek Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Link: https://lore.kernel.org/r/20220624181438.4355-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 4404ca1f98d8..0d258b6e1a43 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -938,6 +938,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, if (IS_ERR(priv->clk_cd)) return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk_cd), "cannot get cd clock"); + priv->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); + if (IS_ERR(priv->rstc)) + return PTR_ERR(priv->rstc); + priv->pinctrl = devm_pinctrl_get(&pdev->dev); if (!IS_ERR(priv->pinctrl)) { priv->pins_default = pinctrl_lookup_state(priv->pinctrl, @@ -1030,10 +1034,6 @@ int renesas_sdhi_probe(struct platform_device *pdev, if (ret) goto efree; - priv->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); - if (IS_ERR(priv->rstc)) - return PTR_ERR(priv->rstc); - ver = sd_ctrl_read16(host, CTL_VERSION); /* GEN2_SDR104 is first known SDHI to use 32bit block count */ if (ver < SDHI_VER_GEN2_SDR104 && mmc_data->max_blk_count > U16_MAX) From 088604048b24846d1e79da4c2a73a6f3ad43edb4 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Jun 2022 19:14:38 +0100 Subject: [PATCH 073/111] mmc: renesas_sdhi: Fix typo's Fix typo's, * difference -> different * alignment -> aligned While at it updated the comment to make it clear that Renesas SDHI DMAC needs buffers to be 128-byte aligned. Reported-by: Pavel Machek Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Link: https://lore.kernel.org/r/20220624181438.4355-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 8f2e6619fa68..0ccdbe3010ee 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -322,7 +322,7 @@ renesas_sdhi_internal_dmac_dataend_dma(struct tmio_mmc_host *host) } /* - * renesas_sdhi_internal_dmac_map() will be called with two difference + * renesas_sdhi_internal_dmac_map() will be called with two different * sg pointers in two mmc_data by .pre_req(), but tmio host can have a single * sg_ptr only. So, renesas_sdhi_internal_dmac_{un}map() should use a sg * pointer in a mmc_data instead of host->sg_ptr. @@ -356,7 +356,7 @@ renesas_sdhi_internal_dmac_map(struct tmio_mmc_host *host, data->host_cookie = cookie; - /* This DMAC cannot handle if buffer is not 128-bytes alignment */ + /* This DMAC needs buffers to be 128-byte aligned */ if (!IS_ALIGNED(sg_dma_address(data->sg), 128)) { renesas_sdhi_internal_dmac_unmap(host, data, cookie); return false; From 2e531bc3e0d86362fcd8a577b3278d9ef3cc2ba0 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 25 Jun 2022 14:55:25 +0200 Subject: [PATCH 074/111] memstick/ms_block: Fix some incorrect memory allocation Some functions of the bitmap API take advantage of the fact that a bitmap is an array of long. So, to make sure this assertion is correct, allocate bitmaps with bitmap_zalloc() instead of kzalloc()+hand-computed number of bytes. While at it, also use bitmap_free() instead of kfree() to keep the semantic. Fixes: 0ab30494bc4f ("memstick: add support for legacy memorysticks") Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/dbf633c48c24ae6d95f852557e8d8b3bbdef65fe.1656155715.git.christophe.jaillet@wanadoo.fr Signed-off-by: Ulf Hansson --- drivers/memstick/core/ms_block.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index 3993bdd4b519..f8f151163667 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c @@ -1341,17 +1341,17 @@ static int msb_ftl_initialize(struct msb_data *msb) msb->zone_count = msb->block_count / MS_BLOCKS_IN_ZONE; msb->logical_block_count = msb->zone_count * 496 - 2; - msb->used_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL); - msb->erased_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL); + msb->used_blocks_bitmap = bitmap_zalloc(msb->block_count, GFP_KERNEL); + msb->erased_blocks_bitmap = bitmap_zalloc(msb->block_count, GFP_KERNEL); msb->lba_to_pba_table = kmalloc_array(msb->logical_block_count, sizeof(u16), GFP_KERNEL); if (!msb->used_blocks_bitmap || !msb->lba_to_pba_table || !msb->erased_blocks_bitmap) { - kfree(msb->used_blocks_bitmap); + bitmap_free(msb->used_blocks_bitmap); + bitmap_free(msb->erased_blocks_bitmap); kfree(msb->lba_to_pba_table); - kfree(msb->erased_blocks_bitmap); return -ENOMEM; } @@ -1946,7 +1946,7 @@ static DEFINE_MUTEX(msb_disk_lock); /* protects against races in open/release */ static void msb_data_clear(struct msb_data *msb) { kfree(msb->boot_page); - kfree(msb->used_blocks_bitmap); + bitmap_free(msb->used_blocks_bitmap); kfree(msb->lba_to_pba_table); kfree(msb->cache); msb->card = NULL; From 54eb7a55be6779c4d0c25eaf5056498a28595049 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 25 Jun 2022 14:55:56 +0200 Subject: [PATCH 075/111] memstick/ms_block: Fix a memory leak 'erased_blocks_bitmap' is never freed. As it is allocated at the same time as 'used_blocks_bitmap', it is likely that it should be freed also at the same time. Add the corresponding bitmap_free() in msb_data_clear(). Fixes: 0ab30494bc4f ("memstick: add support for legacy memorysticks") Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/b3b78926569445962ea5c3b6e9102418a9effb88.1656155715.git.christophe.jaillet@wanadoo.fr Signed-off-by: Ulf Hansson --- drivers/memstick/core/ms_block.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index f8f151163667..f8fdf88fb240 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c @@ -1947,6 +1947,7 @@ static void msb_data_clear(struct msb_data *msb) { kfree(msb->boot_page); bitmap_free(msb->used_blocks_bitmap); + bitmap_free(msb->erased_blocks_bitmap); kfree(msb->lba_to_pba_table); kfree(msb->cache); msb->card = NULL; From aabf199c4eff56e8b36a4c2807c041d93b20c1e1 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 25 Jun 2022 14:56:05 +0200 Subject: [PATCH 076/111] memstick/ms_block: Use the bitmap API when applicable Use bitmap_equal() instead of hand writing it. It improves semantic and avoids some explicit computation to convert a number of bits to a number of bytes. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/b216df8798f765ab14bce65739c220643320f376.1656155715.git.christophe.jaillet@wanadoo.fr Signed-off-by: Ulf Hansson --- drivers/memstick/core/ms_block.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index f8fdf88fb240..c05edfc1c841 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c @@ -2245,8 +2245,8 @@ static int msb_resume(struct memstick_dev *card) goto out; if (msb->block_count != new_msb->block_count || - memcmp(msb->used_blocks_bitmap, new_msb->used_blocks_bitmap, - msb->block_count / 8)) + !bitmap_equal(msb->used_blocks_bitmap, new_msb->used_blocks_bitmap, + msb->block_count)) goto out; card_dead = false; From 2e586f8a5b0ed4a525014a692923ac96f6647816 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 25 Jun 2022 15:17:22 +0200 Subject: [PATCH 077/111] mmc: tmio: avoid glitches when resetting If we reset because of an error, we need to preserve values for the clock frequency. Otherwise, glitches may be seen on the bus. To achieve that, we introduce a 'preserve' parameter to the reset function and the IP core specific reset callbacks to handle everything accordingly. Reported-by: Yoshihiro Shimoda Signed-off-by: Wolfram Sang Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20220625131722.1397-1-wsa@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 29 ++++++++++++++-------------- drivers/mmc/host/tmio_mmc.c | 2 +- drivers/mmc/host/tmio_mmc.h | 6 +++++- drivers/mmc/host/tmio_mmc_core.c | 28 +++++++++++++++++++++------ 4 files changed, 42 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 0d258b6e1a43..55f7b27c3de7 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -49,9 +49,6 @@ #define HOST_MODE_GEN3_32BIT (HOST_MODE_GEN3_WMODE | HOST_MODE_GEN3_BUSWIDTH) #define HOST_MODE_GEN3_64BIT 0 -#define CTL_SDIF_MODE 0xe6 -#define SDIF_MODE_HS400 BIT(0) - #define SDHI_VER_GEN2_SDR50 0x490c #define SDHI_VER_RZ_A1 0x820b /* very old datasheets said 0x490c for SDR104, too. They are wrong! */ @@ -562,23 +559,25 @@ static void renesas_sdhi_scc_reset(struct tmio_mmc_host *host, struct renesas_sd } /* only populated for TMIO_MMC_MIN_RCAR2 */ -static void renesas_sdhi_reset(struct tmio_mmc_host *host) +static void renesas_sdhi_reset(struct tmio_mmc_host *host, bool preserve) { struct renesas_sdhi *priv = host_to_priv(host); int ret; u16 val; - if (priv->rstc) { - reset_control_reset(priv->rstc); - /* Unknown why but without polling reset status, it will hang */ - read_poll_timeout(reset_control_status, ret, ret == 0, 1, 100, - false, priv->rstc); - /* At least SDHI_VER_GEN2_SDR50 needs manual release of reset */ - sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); - priv->needs_adjust_hs400 = false; - renesas_sdhi_set_clock(host, host->clk_cache); - } else if (priv->scc_ctl) { - renesas_sdhi_scc_reset(host, priv); + if (!preserve) { + if (priv->rstc) { + reset_control_reset(priv->rstc); + /* Unknown why but without polling reset status, it will hang */ + read_poll_timeout(reset_control_status, ret, ret == 0, 1, 100, + false, priv->rstc); + /* At least SDHI_VER_GEN2_SDR50 needs manual release of reset */ + sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); + priv->needs_adjust_hs400 = false; + renesas_sdhi_set_clock(host, host->clk_cache); + } else if (priv->scc_ctl) { + renesas_sdhi_scc_reset(host, priv); + } } if (sd_ctrl_read16(host, CTL_VERSION) >= SDHI_VER_GEN3_SD) { diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index b55a29c53d9c..53a2ad9a24b8 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -75,7 +75,7 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, tmio_mmc_clk_start(host); } -static void tmio_mmc_reset(struct tmio_mmc_host *host) +static void tmio_mmc_reset(struct tmio_mmc_host *host, bool preserve) { sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000); usleep_range(10000, 11000); diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index e754bb3f5c32..501613c74406 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -42,6 +42,7 @@ #define CTL_DMA_ENABLE 0xd8 #define CTL_RESET_SD 0xe0 #define CTL_VERSION 0xe2 +#define CTL_SDIF_MODE 0xe6 /* only known on R-Car 2+ */ /* Definitions for values the CTL_STOP_INTERNAL_ACTION register can take */ #define TMIO_STOP_STP BIT(0) @@ -98,6 +99,9 @@ /* Definitions for values the CTL_DMA_ENABLE register can take */ #define DMA_ENABLE_DMASDRW BIT(1) +/* Definitions for values the CTL_SDIF_MODE register can take */ +#define SDIF_MODE_HS400 BIT(0) /* only known on R-Car 2+ */ + /* Define some IRQ masks */ /* This is the mask used at reset by the chip */ #define TMIO_MASK_ALL 0x837f031d @@ -181,7 +185,7 @@ struct tmio_mmc_host { int (*multi_io_quirk)(struct mmc_card *card, unsigned int direction, int blk_size); int (*write16_hook)(struct tmio_mmc_host *host, int addr); - void (*reset)(struct tmio_mmc_host *host); + void (*reset)(struct tmio_mmc_host *host, bool preserve); bool (*check_retune)(struct tmio_mmc_host *host, struct mmc_request *mrq); void (*fixup_request)(struct tmio_mmc_host *host, struct mmc_request *mrq); unsigned int (*get_timeout_cycles)(struct tmio_mmc_host *host); diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index a5850d83908b..437048bb8027 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -179,8 +179,17 @@ static void tmio_mmc_set_bus_width(struct tmio_mmc_host *host, sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, reg); } -static void tmio_mmc_reset(struct tmio_mmc_host *host) +static void tmio_mmc_reset(struct tmio_mmc_host *host, bool preserve) { + u16 card_opt, clk_ctrl, sdif_mode; + + if (preserve) { + card_opt = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT); + clk_ctrl = sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL); + if (host->pdata->flags & TMIO_MMC_MIN_RCAR2) + sdif_mode = sd_ctrl_read16(host, CTL_SDIF_MODE); + } + /* FIXME - should we set stop clock reg here */ sd_ctrl_write16(host, CTL_RESET_SD, 0x0000); usleep_range(10000, 11000); @@ -190,7 +199,7 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host) tmio_mmc_abort_dma(host); if (host->reset) - host->reset(host); + host->reset(host, preserve); sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask_all); host->sdcard_irq_mask = host->sdcard_irq_mask_all; @@ -206,6 +215,13 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host) sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001); } + if (preserve) { + sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, card_opt); + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk_ctrl); + if (host->pdata->flags & TMIO_MMC_MIN_RCAR2) + sd_ctrl_write16(host, CTL_SDIF_MODE, sdif_mode); + } + if (host->mmc->card) mmc_retune_needed(host->mmc); } @@ -248,7 +264,7 @@ static void tmio_mmc_reset_work(struct work_struct *work) spin_unlock_irqrestore(&host->lock, flags); - tmio_mmc_reset(host); + tmio_mmc_reset(host, true); /* Ready for new calls */ host->mrq = NULL; @@ -961,7 +977,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) tmio_mmc_power_off(host); /* For R-Car Gen2+, we need to reset SDHI specific SCC */ if (host->pdata->flags & TMIO_MMC_MIN_RCAR2) - tmio_mmc_reset(host); + tmio_mmc_reset(host, false); host->set_clock(host, 0); break; @@ -1189,7 +1205,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) _host->sdcard_irq_mask_all = TMIO_MASK_ALL; _host->set_clock(_host, 0); - tmio_mmc_reset(_host); + tmio_mmc_reset(_host, false); spin_lock_init(&_host->lock); mutex_init(&_host->ios_lock); @@ -1285,7 +1301,7 @@ int tmio_mmc_host_runtime_resume(struct device *dev) struct tmio_mmc_host *host = dev_get_drvdata(dev); tmio_mmc_clk_enable(host); - tmio_mmc_reset(host); + tmio_mmc_reset(host, false); if (host->clk_cache) host->set_clock(host, host->clk_cache); From f3daa7e6e2ae578778c72de785699942dbfeace4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 26 Jun 2022 14:03:42 +0200 Subject: [PATCH 078/111] dt-bindings: mmc: samsung,s3c6410-sdhci: convert to dtschema Convert the Samsung SoC SDHCI Controller bindings to DT schema. The original bindings were quite old and incomplete, so add during conversion typical (already used) properties like reg, clocks, interrupts. The bindings were not precising the clocks, although the upstream DTS and Linux driver were expecting bus clocks in certain patterns in any order. Document the status quo even though it is not a proper approach for bindings. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20220626120342.38851-6-krzysztof.kozlowski@linaro.org Signed-off-by: Ulf Hansson --- .../bindings/mmc/samsung,s3c6410-sdhci.yaml | 81 +++++++++++++++++++ .../devicetree/bindings/mmc/samsung-sdhci.txt | 32 -------- 2 files changed, 81 insertions(+), 32 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/samsung,s3c6410-sdhci.yaml delete mode 100644 Documentation/devicetree/bindings/mmc/samsung-sdhci.txt diff --git a/Documentation/devicetree/bindings/mmc/samsung,s3c6410-sdhci.yaml b/Documentation/devicetree/bindings/mmc/samsung,s3c6410-sdhci.yaml new file mode 100644 index 000000000000..5d873a60f650 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/samsung,s3c6410-sdhci.yaml @@ -0,0 +1,81 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/samsung,s3c6410-sdhci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung SoC SDHCI Controller + +maintainers: + - Jaehoon Chung + - Krzysztof Kozlowski + +properties: + compatible: + enum: + - samsung,s3c6410-sdhci + - samsung,exynos4210-sdhci + + reg: + maxItems: 1 + + clocks: + minItems: 2 + maxItems: 5 + + clock-names: + minItems: 2 + items: + - const: hsmmc + - pattern: "^mmc_busclk.[0-3]$" + - pattern: "^mmc_busclk.[0-3]$" + - pattern: "^mmc_busclk.[0-3]$" + - pattern: "^mmc_busclk.[0-3]$" + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +allOf: + - $ref: mmc-controller.yaml# + - if: + properties: + compatible: + contains: + enum: + - samsung,exynos4210-sdhci + then: + properties: + clocks: + maxItems: 2 + clock-names: + items: + - const: hsmmc + - const: mmc_busclk.2 + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + mmc@12510000 { + compatible = "samsung,exynos4210-sdhci"; + reg = <0x12510000 0x100>; + interrupts = ; + clocks = <&clock CLK_SDMMC0>, <&clock CLK_SCLK_MMC0>; + clock-names = "hsmmc", "mmc_busclk.2"; + bus-width = <4>; + cd-gpios = <&gpx3 4 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sdhci2_cd>; + pinctrl-names = "default"; + vmmc-supply = <&ldo21_reg>; + }; diff --git a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt deleted file mode 100644 index 42e0a9afa100..000000000000 --- a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt +++ /dev/null @@ -1,32 +0,0 @@ -* Samsung's SDHCI Controller device tree bindings - -Samsung's SDHCI controller is used as a connectivity interface with external -MMC, SD and eMMC storage mediums. This file documents differences between the -core mmc properties described by mmc.txt and the properties used by the -Samsung implementation of the SDHCI controller. - -Required SoC Specific Properties: -- compatible: should be one of the following - - "samsung,s3c6410-sdhci": For controllers compatible with s3c6410 sdhci - controller. - - "samsung,exynos4210-sdhci": For controllers compatible with Exynos4 sdhci - controller. - -Required Board Specific Properties: -- pinctrl-0: Should specify pin control groups used for this controller. -- pinctrl-names: Should contain only one value - "default". - -Example: - sdhci@12530000 { - compatible = "samsung,exynos4210-sdhci"; - reg = <0x12530000 0x100>; - interrupts = <0 75 0>; - bus-width = <4>; - cd-gpios = <&gpk2 2 0>; - pinctrl-names = "default"; - pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>; - }; - - Note: This example shows both SoC specific and board specific properties - in a single device node. The properties can be actually be separated - into SoC specific node and board specific node. From e427266460826bea21b70f9b2bb29decfb2c2620 Mon Sep 17 00:00:00 2001 From: ChanWoo Lee Date: Wed, 6 Jul 2022 09:48:40 +0900 Subject: [PATCH 079/111] mmc: core: Replace with already defined values for readability SD_ROCR_S18A is already defined and is used to check the rocr value, so let's replace with already defined values for readability. Signed-off-by: ChanWoo Lee Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20220706004840.24812-1-cw9316.lee@samsung.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index c5f1df6ce4c0..d2023837dd72 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -870,7 +870,7 @@ try_again: * the CCS bit is set as well. We deliberately deviate from the spec in * regards to this, which allows UHS-I to be supported for SDSC cards. */ - if (!mmc_host_is_spi(host) && rocr && (*rocr & 0x01000000)) { + if (!mmc_host_is_spi(host) && rocr && (*rocr & SD_ROCR_S18A)) { err = mmc_set_uhs_voltage(host, pocr); if (err == -EAGAIN) { retries--; From 5987e6ded29d52e42fc7b06aa575c60a25eee38e Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Thu, 30 Jun 2022 12:09:26 +0300 Subject: [PATCH 080/111] mmc: sdhci-of-at91: fix set_uhs_signaling rewriting of MC1R In set_uhs_signaling, the DDR bit is being set by fully writing the MC1R register. This can lead to accidental erase of certain bits in this register. Avoid this by doing a read-modify-write operation. Fixes: d0918764c17b ("mmc: sdhci-of-at91: fix MMC_DDR_52 timing selection") Signed-off-by: Eugen Hristev Tested-by: Karl Olsen Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20220630090926.15061-1-eugen.hristev@microchip.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-at91.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c index 10fb4cb2c731..cd0134580a90 100644 --- a/drivers/mmc/host/sdhci-of-at91.c +++ b/drivers/mmc/host/sdhci-of-at91.c @@ -100,8 +100,13 @@ static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock) static void sdhci_at91_set_uhs_signaling(struct sdhci_host *host, unsigned int timing) { - if (timing == MMC_TIMING_MMC_DDR52) - sdhci_writeb(host, SDMMC_MC1R_DDR, SDMMC_MC1R); + u8 mc1r; + + if (timing == MMC_TIMING_MMC_DDR52) { + mc1r = sdhci_readb(host, SDMMC_MC1R); + mc1r |= SDMMC_MC1R_DDR; + sdhci_writeb(host, mc1r, SDMMC_MC1R); + } sdhci_set_uhs_signaling(host, timing); } From 95a4cf7172bc356f072df4eea4d8d307bdb38d86 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 4 Jul 2022 16:35:53 +0200 Subject: [PATCH 081/111] dt-bindings: mmc: sdhci-msm: document resets Commit "mmc: sdhci-msm: Reset GCC_SDCC_BCR register for SDHC" added support for utilizing a hardware reset and parsing it from DT, however the bindings were not updated along with it. So, document the usage of "resets" property with the limit of only one item. Signed-off-by: Robert Marko Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220704143554.1180927-1-robimarko@gmail.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-msm.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index 31a3ce208e1a..ca8814a80443 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -116,6 +116,9 @@ properties: description: Should specify pin control groups used for this controller. + resets: + maxItems: 1 + qcom,ddr-config: $ref: /schemas/types.yaml#/definitions/uint32 description: platform specific settings for DDR_CONFIG reg. From 4ec43b8797b817344cab8359e7734563a6bf3afc Mon Sep 17 00:00:00 2001 From: Johnson Wang Date: Fri, 8 Jul 2022 19:47:47 +0800 Subject: [PATCH 082/111] dt-bindings: mmc: Add compatible for MediaTek MT8188 This commit adds dt-binding documentation of mmc for MediaTek MT8188 SoC platform. Signed-off-by: Johnson Wang Reviewed-by: AngeloGioacchino Del Regno Acked-by: Rob Herring Link: https://lore.kernel.org/r/20220708114747.13878-1-johnson.wang@mediatek.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml index 2a2e9fa8c188..be366cefffc2 100644 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml @@ -30,13 +30,11 @@ properties: - const: mediatek,mt7623-mmc - const: mediatek,mt2701-mmc - items: - - const: mediatek,mt8186-mmc - - const: mediatek,mt8183-mmc - - items: - - const: mediatek,mt8192-mmc - - const: mediatek,mt8183-mmc - - items: - - const: mediatek,mt8195-mmc + - enum: + - mediatek,mt8186-mmc + - mediatek,mt8188-mmc + - mediatek,mt8192-mmc + - mediatek,mt8195-mmc - const: mediatek,mt8183-mmc reg: From 331ad8247b46eeaf3b5c66e5ef5986630fe0f043 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 12 Jul 2022 16:42:41 +0200 Subject: [PATCH 083/111] dt-bindings: mmc: sdhci-msm: fix reg-names entries Bindings before conversion to DT schema expected reg-names without "_mem" suffix. This was used by older DTS files and by the MSM SDHCI driver. Reported-by: Douglas Anderson Fixes: edfbf8c307ff ("dt-bindings: mmc: sdhci-msm: Fix issues in yaml bindings") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20220712144245.17417-2-krzysztof.kozlowski@linaro.org Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/sdhci-msm.yaml | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index ca8814a80443..c67e17792fd3 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -59,22 +59,22 @@ properties: maxItems: 4 oneOf: - items: - - const: hc_mem + - const: hc - items: - - const: hc_mem - - const: core_mem + - const: hc + - const: core - items: - - const: hc_mem - - const: cqe_mem + - const: hc + - const: cqhci - items: - - const: hc_mem - - const: cqe_mem - - const: ice_mem + - const: hc + - const: cqhci + - const: ice - items: - - const: hc_mem - - const: core_mem - - const: cqe_mem - - const: ice_mem + - const: hc + - const: core + - const: cqhci + - const: ice clocks: minItems: 3 From 54c16b522e00583ba1151501286b0cf4c91e08c3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 12 Jul 2022 16:42:42 +0200 Subject: [PATCH 084/111] dt-bindings: mmc: sdhci-msm: constrain reg-names per variants The entries in arrays must have fixed order, so the bindings and Linux driver expecting various combinations of 'reg' addresses was never actually conforming to guidelines. The 'core' reg entry is valid only for SDCC v4 and lower, so disallow it in SDCC v5. SDCC v4 supports CQE and ICE, so allow them, even though the qcom,sdhci-msm-v4 compatible is used also for earlier SoCs with SDCC v2 or v3, so it is not entirely accurate. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20220712144245.17417-3-krzysztof.kozlowski@linaro.org Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/sdhci-msm.yaml | 61 ++++++++++++------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index c67e17792fd3..edd370d1043d 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -48,33 +48,11 @@ properties: reg: minItems: 1 - items: - - description: Host controller register map - - description: SD Core register map - - description: CQE register map - - description: Inline Crypto Engine register map + maxItems: 4 reg-names: minItems: 1 maxItems: 4 - oneOf: - - items: - - const: hc - - items: - - const: hc - - const: core - - items: - - const: hc - - const: cqhci - - items: - - const: hc - - const: cqhci - - const: ice - - items: - - const: hc - - const: core - - const: cqhci - - const: ice clocks: minItems: 3 @@ -179,6 +157,43 @@ required: allOf: - $ref: mmc-controller.yaml# + - if: + properties: + compatible: + contains: + enum: + - qcom,sdhci-msm-v4 + then: + properties: + reg: + minItems: 2 + items: + - description: Host controller register map + - description: SD Core register map + - description: CQE register map + - description: Inline Crypto Engine register map + reg-names: + minItems: 2 + items: + - const: hc + - const: core + - const: cqhci + - const: ice + else: + properties: + reg: + minItems: 1 + items: + - description: Host controller register map + - description: CQE register map + - description: Inline Crypto Engine register map + reg-names: + minItems: 1 + items: + - const: hc + - const: cqhci + - const: ice + unevaluatedProperties: false examples: From 3beb0ab5bffba625007ea5c9e5e0ee5eef05c1ea Mon Sep 17 00:00:00 2001 From: Seunghui Lee Date: Wed, 13 Jul 2022 12:36:34 +0900 Subject: [PATCH 085/111] mmc: core: Use mmc_card_* macro and add a new for the sd_combo type Add mmc_card_sd_combo() macro for sd combo type card and use the mmc_card_* macro to simplify code instead of comparing card->type. Signed-off-by: Seunghui Lee Link: https://lore.kernel.org/r/20220713033635.28432-2-sh043.lee@samsung.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/block.c | 4 ++-- drivers/mmc/core/bus.c | 4 ++-- drivers/mmc/core/sd.c | 2 +- drivers/mmc/core/sdio.c | 16 ++++++++-------- include/linux/mmc/card.h | 1 + 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index f4a1281658db..9c642b3b7c20 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -2988,7 +2988,7 @@ static int mmc_blk_probe(struct mmc_card *card) * Don't enable runtime PM for SD-combo cards here. Leave that * decision to be taken during the SDIO init sequence instead. */ - if (card->type != MMC_TYPE_SD_COMBO) { + if (!mmc_card_sd_combo(card)) { pm_runtime_set_active(&card->dev); pm_runtime_enable(&card->dev); } @@ -3015,7 +3015,7 @@ static void mmc_blk_remove(struct mmc_card *card) mmc_blk_part_switch(card, md->part_type); mmc_release_host(card->host); } - if (card->type != MMC_TYPE_SD_COMBO) + if (!mmc_card_sd_combo(card)) pm_runtime_disable(&card->dev); pm_runtime_put_noidle(&card->dev); mmc_blk_remove_req(md); diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 58a60afa650b..d8762fa3d5cd 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -85,7 +85,7 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) return retval; } - if (card->type == MMC_TYPE_SDIO || card->type == MMC_TYPE_SD_COMBO) { + if (mmc_card_sdio(card) || mmc_card_sd_combo(card)) { retval = add_uevent_var(env, "SDIO_ID=%04X:%04X", card->cis.vendor, card->cis.device); if (retval) @@ -107,7 +107,7 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) * SDIO (non-combo) cards are not handled by mmc_block driver and do not * have accessible CID register which used by mmc_card_name() function. */ - if (card->type == MMC_TYPE_SDIO) + if (mmc_card_sdio(card)) return 0; retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index d2023837dd72..cee4c0b59f43 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -793,7 +793,7 @@ static umode_t sd_std_is_visible(struct kobject *kobj, struct attribute *attr, attr == &dev_attr_info2.attr || attr == &dev_attr_info3.attr || attr == &dev_attr_info4.attr - ) && card->type != MMC_TYPE_SD_COMBO) + ) &&!mmc_card_sd_combo(card)) return 0; return attr->mode; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 25799accf8a0..b589df1c35e0 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -335,7 +335,7 @@ static int sdio_disable_4bit_bus(struct mmc_card *card) { int err; - if (card->type == MMC_TYPE_SDIO) + if (mmc_card_sdio(card)) goto out; if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) @@ -360,7 +360,7 @@ static int sdio_enable_4bit_bus(struct mmc_card *card) err = sdio_enable_wide(card); if (err <= 0) return err; - if (card->type == MMC_TYPE_SDIO) + if (mmc_card_sdio(card)) goto out; if (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4) { @@ -415,7 +415,7 @@ static int sdio_enable_hs(struct mmc_card *card) int ret; ret = mmc_sdio_switch_hs(card, true); - if (ret <= 0 || card->type == MMC_TYPE_SDIO) + if (ret <= 0 || mmc_card_sdio(card)) return ret; ret = mmc_sd_switch_hs(card); @@ -441,7 +441,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card) max_dtr = card->cis.max_dtr; } - if (card->type == MMC_TYPE_SD_COMBO) + if (mmc_card_sd_combo(card)) max_dtr = min(max_dtr, mmc_sd_get_max_clock(card)); return max_dtr; @@ -689,7 +689,7 @@ try_again: mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) { card->type = MMC_TYPE_SD_COMBO; - if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO || + if (oldcard && (!mmc_card_sd_combo(oldcard) || memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) { err = -ENOENT; goto mismatch; @@ -697,7 +697,7 @@ try_again: } else { card->type = MMC_TYPE_SDIO; - if (oldcard && oldcard->type != MMC_TYPE_SDIO) { + if (oldcard && !mmc_card_sdio(oldcard)) { err = -ENOENT; goto mismatch; } @@ -754,7 +754,7 @@ try_again: /* * Read CSD, before selecting the card */ - if (!oldcard && card->type == MMC_TYPE_SD_COMBO) { + if (!oldcard && mmc_card_sd_combo(card)) { err = mmc_sd_get_csd(card); if (err) goto remove; @@ -827,7 +827,7 @@ try_again: mmc_fixup_device(card, sdio_fixup_methods); - if (card->type == MMC_TYPE_SD_COMBO) { + if (mmc_card_sd_combo(card)) { err = mmc_sd_setup_card(host, card, oldcard != NULL); /* handle as SDIO-only card if memory init failed */ if (err) { diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 37f975875102..156a7b673a28 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -348,5 +348,6 @@ bool mmc_card_is_blockaddr(struct mmc_card *card); #define mmc_card_mmc(c) ((c)->type == MMC_TYPE_MMC) #define mmc_card_sd(c) ((c)->type == MMC_TYPE_SD) #define mmc_card_sdio(c) ((c)->type == MMC_TYPE_SDIO) +#define mmc_card_sd_combo(c) ((c)->type == MMC_TYPE_SD_COMBO) #endif /* LINUX_MMC_CARD_H */ From c095449ea9812bafba71735fdc79e7b2ca0f4701 Mon Sep 17 00:00:00 2001 From: Seunghui Lee Date: Wed, 13 Jul 2022 12:36:35 +0900 Subject: [PATCH 086/111] mmc: mxcmmc: Use mmc_card_sdio macro Use mmc_card_sdio macro to simplify code. Signed-off-by: Seunghui Lee Link: https://lore.kernel.org/r/20220713033635.28432-3-sh043.lee@samsung.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mxcmmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 613f13306433..2cf0413407ea 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -923,7 +923,7 @@ static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card) * One way to prevent this is to only allow 1-bit transfers. */ - if (is_imx31_mmc(mxcmci) && card->type == MMC_TYPE_SDIO) + if (is_imx31_mmc(mxcmci) && mmc_card_sdio(card)) host->caps &= ~MMC_CAP_4_BIT_DATA; else host->caps |= MMC_CAP_4_BIT_DATA; From b3fa3e6dccc465969721b8bd2824213bd235efeb Mon Sep 17 00:00:00 2001 From: Christian Loehle Date: Fri, 1 Jul 2022 12:43:09 +0000 Subject: [PATCH 087/111] mmc: block: Add single read for 4k sector cards Cards with 4k native sector size may only be read 4k-aligned, accommodate for this in the single read recovery and use it. Fixes: 81196976ed946 (mmc: block: Add blk-mq support) Signed-off-by: Christian Loehle Acked-by: Adrian Hunter Reviewed-by: Avri Altman Link: https://lore.kernel.org/r/cf4f316274c5474586d0d99b17db4a4c@hyperstone.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/block.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 9c642b3b7c20..828e89ff0629 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -176,7 +176,7 @@ static inline int mmc_blk_part_switch(struct mmc_card *card, unsigned int part_type); static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, struct mmc_card *card, - int disable_multi, + int recovery_mode, struct mmc_queue *mq); static void mmc_blk_hsq_req_done(struct mmc_request *mrq); @@ -1302,7 +1302,7 @@ static void mmc_blk_eval_resp_error(struct mmc_blk_request *brq) } static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq, - int disable_multi, bool *do_rel_wr_p, + int recovery_mode, bool *do_rel_wr_p, bool *do_data_tag_p) { struct mmc_blk_data *md = mq->blkdata; @@ -1368,12 +1368,12 @@ static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq, brq->data.blocks--; /* - * After a read error, we redo the request one sector + * After a read error, we redo the request one (native) sector * at a time in order to accurately determine which * sectors can be read successfully. */ - if (disable_multi) - brq->data.blocks = 1; + if (recovery_mode) + brq->data.blocks = queue_physical_block_size(mq->queue) >> 9; /* * Some controllers have HW issues while operating @@ -1590,7 +1590,7 @@ static int mmc_blk_cqe_issue_rw_rq(struct mmc_queue *mq, struct request *req) static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, struct mmc_card *card, - int disable_multi, + int recovery_mode, struct mmc_queue *mq) { u32 readcmd, writecmd; @@ -1599,7 +1599,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, struct mmc_blk_data *md = mq->blkdata; bool do_rel_wr, do_data_tag; - mmc_blk_data_prep(mq, mqrq, disable_multi, &do_rel_wr, &do_data_tag); + mmc_blk_data_prep(mq, mqrq, recovery_mode, &do_rel_wr, &do_data_tag); brq->mrq.cmd = &brq->cmd; @@ -1690,7 +1690,7 @@ static int mmc_blk_fix_state(struct mmc_card *card, struct request *req) #define MMC_READ_SINGLE_RETRIES 2 -/* Single sector read during recovery */ +/* Single (native) sector read during recovery */ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req) { struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); @@ -1698,6 +1698,7 @@ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req) struct mmc_card *card = mq->card; struct mmc_host *host = card->host; blk_status_t error = BLK_STS_OK; + size_t bytes_per_read = queue_physical_block_size(mq->queue); do { u32 status; @@ -1732,13 +1733,13 @@ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req) else error = BLK_STS_OK; - } while (blk_update_request(req, error, 512)); + } while (blk_update_request(req, error, bytes_per_read)); return; error_exit: mrq->data->bytes_xfered = 0; - blk_update_request(req, BLK_STS_IOERR, 512); + blk_update_request(req, BLK_STS_IOERR, bytes_per_read); /* Let it try the remaining request again */ if (mqrq->retries > MMC_MAX_RETRIES - 1) mqrq->retries = MMC_MAX_RETRIES - 1; @@ -1879,10 +1880,9 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req) return; } - /* FIXME: Missing single sector read for large sector size */ - if (!mmc_large_sector(card) && rq_data_dir(req) == READ && - brq->data.blocks > 1) { - /* Read one sector at a time */ + if (rq_data_dir(req) == READ && brq->data.blocks > + queue_physical_block_size(mq->queue) >> 9) { + /* Read one (native) sector at a time */ mmc_blk_read_single(mq, req); return; } From 9b538b0e3a95e5b7a52e9eaf3ae51686608bf333 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 14 Jul 2022 11:10:40 +0200 Subject: [PATCH 088/111] dt-bindings: mmc: sdhci-msm: add MSM8998 Add a MSM8998-specific SDCC compatible, because using only a generic qcom,sdhci-msm-v4 fallback is deprecated. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20220714091042.22287-2-krzysztof.kozlowski@linaro.org Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-msm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index edd370d1043d..34956182dbb2 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -30,6 +30,7 @@ properties: - qcom,msm8992-sdhci - qcom,msm8994-sdhci - qcom,msm8996-sdhci + - qcom,msm8998-sdhci - const: qcom,sdhci-msm-v4 # for sdcc versions less than 5.0 - items: - enum: From b05cd716e3bd6e303054058007722819c47c1179 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 14 Jul 2022 11:10:42 +0200 Subject: [PATCH 089/111] mmc: sdhci-msm: drop redundant of_device_id entries This reverts three commits: 1. Revert "mmc: sdhci-msm: Add compatible string check for sdx65" This reverts commit 953706844f0f2fd4dc6984cc010fe6cf51c041f2. 2. Revert "mmc: sdhci-msm: Add compatible string check for sm8150" This reverts commit 5acd6adb65802cc6f9986be3750179a820580d37. 3. Revert "mmc: sdhci-msm: Add SoC specific compatibles" This reverts commit 466614a9765c6fb67e1464d0a3f1261db903834b. The oldest commit 466614a9765c ("mmc: sdhci-msm: Add SoC specific compatibles") did not specify what benefits such multiple compatibles bring, therefore assume there is none. On the other hand such approach brings a lot of churn to driver maintenance by expecting commit for every new compatible, even though it is already covered by the fallback. There is really no sense in duplicating of_device_id for each variant, which is already covered by generic compatible fallback qcom,sdhci-msm-v4 or qcom,sdhci-msm-v5. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20220714091042.22287-4-krzysztof.kozlowski@linaro.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-msm.c | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index e395411fb6fd..dc2991422a87 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -2435,33 +2435,12 @@ static const struct sdhci_msm_variant_info sdm845_sdhci_var = { }; static const struct of_device_id sdhci_msm_dt_match[] = { - /* Following two entries are deprecated (kept only for backward compatibility) */ + /* + * Do not add new variants to the driver which are compatible with + * generic ones, unless they need customization. + */ {.compatible = "qcom,sdhci-msm-v4", .data = &sdhci_msm_mci_var}, {.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var}, - /* Add entries for sdcc versions less than 5.0 here */ - {.compatible = "qcom,apq8084-sdhci", .data = &sdhci_msm_mci_var}, - {.compatible = "qcom,msm8226-sdhci", .data = &sdhci_msm_mci_var}, - {.compatible = "qcom,msm8916-sdhci", .data = &sdhci_msm_mci_var}, - {.compatible = "qcom,msm8953-sdhci", .data = &sdhci_msm_mci_var}, - {.compatible = "qcom,msm8974-sdhci", .data = &sdhci_msm_mci_var}, - {.compatible = "qcom,msm8992-sdhci", .data = &sdhci_msm_mci_var}, - {.compatible = "qcom,msm8994-sdhci", .data = &sdhci_msm_mci_var}, - {.compatible = "qcom,msm8996-sdhci", .data = &sdhci_msm_mci_var}, - /* - * Add entries for sdcc version 5.0 here. For SDCC version 5.0.0, - * MCI registers are removed from SDCC interface and some registers - * are moved to HC. - */ - {.compatible = "qcom,qcs404-sdhci", .data = &sdhci_msm_v5_var}, - {.compatible = "qcom,sdx55-sdhci", .data = &sdhci_msm_v5_var}, - {.compatible = "qcom,sdx65-sdhci", .data = &sdhci_msm_v5_var}, - {.compatible = "qcom,sdm630-sdhci", .data = &sdhci_msm_v5_var}, - {.compatible = "qcom,sm6125-sdhci", .data = &sdhci_msm_v5_var}, - {.compatible = "qcom,sm6350-sdhci", .data = &sdhci_msm_v5_var}, - {.compatible = "qcom,sm8150-sdhci", .data = &sdhci_msm_v5_var}, - {.compatible = "qcom,sm8250-sdhci", .data = &sdhci_msm_v5_var}, - {.compatible = "qcom,sc7280-sdhci", .data = &sdhci_msm_v5_var}, - /* Add entries where soc specific handling is required, here */ {.compatible = "qcom,sdm845-sdhci", .data = &sdm845_sdhci_var}, {.compatible = "qcom,sc7180-sdhci", .data = &sdm845_sdhci_var}, {}, From 99ce0f754c39b0a9ef60879f1bebf725c26e0a9f Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Thu, 14 Jul 2022 14:34:03 +0200 Subject: [PATCH 090/111] dt-bindings: mmc: sdhci-msm: Document the SM8450 compatible Document the compatible for SDHCI on SM8450. Signed-off-by: Konrad Dybcio Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220714123406.1919836-2-konrad.dybcio@somainline.org Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-msm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index 34956182dbb2..b00578ae1dea 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -45,6 +45,7 @@ properties: - qcom,sm6350-sdhci - qcom,sm8150-sdhci - qcom,sm8250-sdhci + - qcom,sm8450-sdhci - const: qcom,sdhci-msm-v5 # for sdcc version 5.0 reg: From 886201c70a1cab34ef96f867c2b2dd6379ffa7b9 Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Thu, 14 Jul 2022 13:41:32 -0400 Subject: [PATCH 091/111] mmc: sdhci-brcmstb: use clk_get_rate(base_clk) in PM resume Use clk_get_rate for base_clk on resume before setting new rate. This change ensures that the clock api returns current rate and sets the clock to the desired rate and honors CLK_GET_NO_CACHE attribute used by clock api. Fixes: 97904a59855c (mmc: sdhci-brcmstb: Add ability to increase max clock rate for 72116b0) Signed-off-by: Kamal Dasu Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20220714174132.18541-1-kdasu.kdev@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-brcmstb.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 28e9cf995c41..aff36a933ebe 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -406,7 +406,14 @@ static int sdhci_brcmstb_resume(struct device *dev) ret = sdhci_pltfm_resume(dev); if (!ret && priv->base_freq_hz) { ret = clk_prepare_enable(priv->base_clk); - if (!ret) + /* + * Note: using clk_get_rate() below as clk_get_rate() + * honors CLK_GET_RATE_NOCACHE attribute, but clk_set_rate() + * may do implicit get_rate() calls that do not honor + * CLK_GET_RATE_NOCACHE. + */ + if (!ret && + (clk_get_rate(priv->base_clk) != priv->base_freq_hz)) ret = clk_set_rate(priv->base_clk, priv->base_freq_hz); } From 86cb0defe0e275453bc39e856bb523eb425a6537 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 8 Jul 2022 18:01:52 +0100 Subject: [PATCH 092/111] 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), From 820f5ce999d2f99961e88c16d65cd26764df0590 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 8 Jul 2022 18:01:53 +0100 Subject: [PATCH 093/111] 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); } From c3266ee185b59e5aab3e0f982e5b7f95d31555a7 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 6 Jul 2022 08:13:27 -0300 Subject: [PATCH 094/111] 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); From d0b55afa47694f6f61b40f578ede7bde1648fe48 Mon Sep 17 00:00:00 2001 From: Fenghua Yu Date: Wed, 6 Jul 2022 17:20:52 -0700 Subject: [PATCH 095/111] 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, }; From e0c7ea83f006ce8c3264ef8b6508a891d886ad4f Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 7 Jul 2022 11:00:29 +0800 Subject: [PATCH 096/111] 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; }; From f66d59180bae2f0e8979962c3df4d445b3ac50d0 Mon Sep 17 00:00:00 2001 From: XueBing Chen Date: Mon, 11 Jul 2022 22:05:33 +0800 Subject: [PATCH 097/111] 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); } From 883c1d6fa4368a63cae2d6ae2d9c91141c60e233 Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 19 Jul 2022 17:10:51 +0800 Subject: [PATCH 098/111] mmc: core: quirks: Add of_node_put() when breaking out of loop In mmc_fixup_of_compatible_match(), we should call of_node_put() when breaking out of for_each_child_of_node() which will increase and decrease the refcount during one iteration. Fixes: b360b1102670 ("mmc: core: allow to match the device tree to apply quirks") Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220719091051.1210806-1-windhl@126.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/quirks.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h index f879dc63d936..be4393988086 100644 --- a/drivers/mmc/core/quirks.h +++ b/drivers/mmc/core/quirks.h @@ -163,8 +163,10 @@ static inline bool mmc_fixup_of_compatible_match(struct mmc_card *card, struct device_node *np; for_each_child_of_node(mmc_dev(card->host)->of_node, np) { - if (of_device_is_compatible(np, compatible)) + if (of_device_is_compatible(np, compatible)) { + of_node_put(np); return true; + } } return false; From 19bbb49acf8d7a03cb83e05624363741a4c3ec6f Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 19 Jul 2022 17:52:15 +0800 Subject: [PATCH 099/111] mmc: cavium-octeon: Add of_node_put() when breaking out of loop In octeon_mmc_probe(), we should call of_node_put() when breaking out of for_each_child_of_node() which has increased and decreased the refcount during each iteration. Fixes: 01d95843335c ("mmc: cavium: Add MMC support for Octeon SOCs.") Signed-off-by: Liang He Acked-by: Robert Richter Link: https://lore.kernel.org/r/20220719095216.1241601-1-windhl@126.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/cavium-octeon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/cavium-octeon.c b/drivers/mmc/host/cavium-octeon.c index 2c4b2df52adb..12dca91a8ef6 100644 --- a/drivers/mmc/host/cavium-octeon.c +++ b/drivers/mmc/host/cavium-octeon.c @@ -277,6 +277,7 @@ static int octeon_mmc_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Error populating slots\n"); octeon_mmc_set_shared_power(host, 0); + of_node_put(cn); goto error; } i++; From 7ee480795e41db314f2c445c65ed854a5d6e8e32 Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 19 Jul 2022 17:52:16 +0800 Subject: [PATCH 100/111] mmc: cavium-thunderx: Add of_node_put() when breaking out of loop In thunder_mmc_probe(), we should call of_node_put() when breaking out of for_each_child_of_node() which has increased and decreased the refcount during each iteration. Fixes: 166bac38c3c5 ("mmc: cavium: Add MMC PCI driver for ThunderX SOCs") Signed-off-by: Liang He Acked-by: Robert Richter Link: https://lore.kernel.org/r/20220719095216.1241601-2-windhl@126.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/cavium-thunderx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/cavium-thunderx.c b/drivers/mmc/host/cavium-thunderx.c index 76013bbbcff3..202b1d6da678 100644 --- a/drivers/mmc/host/cavium-thunderx.c +++ b/drivers/mmc/host/cavium-thunderx.c @@ -142,8 +142,10 @@ static int thunder_mmc_probe(struct pci_dev *pdev, continue; ret = cvm_mmc_of_slot_probe(&host->slot_pdev[i]->dev, host); - if (ret) + if (ret) { + of_node_put(child_node); goto error; + } } i++; } From 00e8c11c137b2e4b2bf54dc9881cf32e3441ddb4 Mon Sep 17 00:00:00 2001 From: Takeshi Saito Date: Wed, 20 Jul 2022 09:29:01 +0200 Subject: [PATCH 101/111] mmc: renesas_sdhi: newer SoCs don't need manual tap correction The newest Gen3 SoCs and Gen4 SoCs do not need manual tap correction with HS400 anymore. So, instead of checking the SDHI version, add a quirk flag and set manual tap correction only for affected SoCs. Signed-off-by: Takeshi Saito [wsa: rebased, renamed the quirk variable, removed stale comment] Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20220720072901.1266-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi.h | 1 + drivers/mmc/host/renesas_sdhi_core.c | 5 ++--- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 6 ++++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index 1a1e3e020a8c..c4abfee1ebae 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -43,6 +43,7 @@ struct renesas_sdhi_quirks { bool hs400_4taps; bool fixed_addr_mode; bool dma_one_rx_only; + bool manual_tap_correction; u32 hs400_bad_taps; const u8 (*hs400_calib_table)[SDHI_CALIB_TABLE_MAX]; }; diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 55f7b27c3de7..6edbf5c161ab 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -380,8 +380,7 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc) sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, priv->scc_tappos_hs400); - /* Gen3 can't do automatic tap correction with HS400, so disable it */ - if (sd_ctrl_read16(host, CTL_VERSION) == SDHI_VER_GEN3_SDMMC) + if (priv->quirks && priv->quirks->manual_tap_correction) sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); @@ -718,7 +717,7 @@ static bool renesas_sdhi_manual_correction(struct tmio_mmc_host *host, bool use_ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0); /* Change TAP position according to correction status */ - if (sd_ctrl_read16(host, CTL_VERSION) == SDHI_VER_GEN3_SDMMC && + if (priv->quirks && priv->quirks->manual_tap_correction && host->mmc->ios.timing == MMC_TIMING_MMC_HS400) { u32 bad_taps = priv->quirks ? priv->quirks->hs400_bad_taps : 0; /* diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 0ccdbe3010ee..42937596c4c4 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -170,6 +170,7 @@ static const struct renesas_sdhi_quirks sdhi_quirks_4tap_nohs400_one_rx = { static const struct renesas_sdhi_quirks sdhi_quirks_4tap = { .hs400_4taps = true, .hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7), + .manual_tap_correction = true, }; static const struct renesas_sdhi_quirks sdhi_quirks_nohs400 = { @@ -182,25 +183,30 @@ static const struct renesas_sdhi_quirks sdhi_quirks_fixed_addr = { static const struct renesas_sdhi_quirks sdhi_quirks_bad_taps1357 = { .hs400_bad_taps = BIT(1) | BIT(3) | BIT(5) | BIT(7), + .manual_tap_correction = true, }; static const struct renesas_sdhi_quirks sdhi_quirks_bad_taps2367 = { .hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7), + .manual_tap_correction = true, }; static const struct renesas_sdhi_quirks sdhi_quirks_r8a7796_es13 = { .hs400_4taps = true, .hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7), .hs400_calib_table = r8a7796_es13_calib_table, + .manual_tap_correction = true, }; static const struct renesas_sdhi_quirks sdhi_quirks_r8a77965 = { .hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7), .hs400_calib_table = r8a77965_calib_table, + .manual_tap_correction = true, }; static const struct renesas_sdhi_quirks sdhi_quirks_r8a77990 = { .hs400_calib_table = r8a77990_calib_table, + .manual_tap_correction = true, }; /* From 37a0d69d00f50f2a0c387bbbbb2946e771af243d Mon Sep 17 00:00:00 2001 From: Akhil R Date: Wed, 20 Jul 2022 16:10:43 +0530 Subject: [PATCH 102/111] 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 --- .../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": From 36834c67016794b8fa03d7672a5b7f2cc4529298 Mon Sep 17 00:00:00 2001 From: Akhil R Date: Wed, 20 Jul 2022 16:10:44 +0530 Subject: [PATCH 103/111] 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, }, { }, }; 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: [PATCH 104/111] 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) From 7d3a3aaaa9cc8ec53e9ef4f3e1711827107f76c5 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 22 Jul 2022 09:44:30 +0100 Subject: [PATCH 105/111] 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); From d2f35ed0aae12bf7b3c5f9bae41b0ada4a292f20 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Sun, 24 Jul 2022 02:13:24 +0530 Subject: [PATCH 106/111] dt-bindings: mmc: rockchip-dw-mshc: Document Rockchip RV1126 Add a compatible string for Rockchip RV1126 SoC. Signed-off-by: Jagan Teki Acked-by: Rob Herring Link: https://lore.kernel.org/r/20220723204335.750095-12-jagan@edgeble.ai Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml index 54fb59820d2b..8d888b435817 100644 --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml @@ -39,6 +39,7 @@ properties: - rockchip,rk3399-dw-mshc - rockchip,rk3568-dw-mshc - rockchip,rv1108-dw-mshc + - rockchip,rv1126-dw-mshc - const: rockchip,rk3288-dw-mshc reg: From 035cc3951797df0e1e831f9fd71b7cda63e71705 Mon Sep 17 00:00:00 2001 From: Axe Yang Date: Tue, 26 Jul 2022 14:28:40 +0800 Subject: [PATCH 107/111] dt-bindings: mmc: mtk-sd: extend interrupts and pinctrls properties Extend interrupts and pinctrls for SDIO wakeup interrupt feature. This feature allow SDIO devices alarm asynchronous interrupt to host even when host stop providing clock to SDIO card. An extra wakeup interrupt and pinctrl states for SDIO DAT1 pin state switching are required in this scenario. Reviewed-by: Rob Herring Signed-off-by: Axe Yang Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220726062842.18846-2-axe.yang@mediatek.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/mtk-sd.yaml | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml index be366cefffc2..083d1ec2f661 100644 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml @@ -70,12 +70,27 @@ properties: - const: ahb_cg interrupts: - maxItems: 1 + description: + Should at least contain MSDC GIC interrupt. To support SDIO in-band wakeup, an extended + interrupt is required and be configured as wakeup source irq. + minItems: 1 + maxItems: 2 + + interrupt-names: + items: + - const: msdc + - const: sdio_wakeup pinctrl-names: + description: + Should at least contain default and state_uhs. To support SDIO in-band wakeup, dat1 pin + will be switched between GPIO mode and SDIO DAT1 mode, state_eint is mandatory in this + scenario. + minItems: 2 items: - const: default - const: state_uhs + - const: state_eint pinctrl-0: description: @@ -87,6 +102,11 @@ properties: should contain uhs mode pin ctrl. maxItems: 1 + pinctrl-2: + description: + should switch dat1 pin to GPIO mode. + maxItems: 1 + assigned-clocks: description: PLL of the source clock. @@ -206,4 +226,32 @@ examples: mediatek,hs400-cmd-resp-sel-rising; }; + mmc3: mmc@11260000 { + compatible = "mediatek,mt8173-mmc"; + reg = <0x11260000 0x1000>; + clock-names = "source", "hclk"; + clocks = <&pericfg CLK_PERI_MSDC30_3>, + <&topckgen CLK_TOP_MSDC50_2_H_SEL>; + interrupt-names = "msdc", "sdio_wakeup"; + interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_LOW 0>, + <&pio 23 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default", "state_uhs", "state_eint"; + pinctrl-0 = <&mmc2_pins_default>; + pinctrl-1 = <&mmc2_pins_uhs>; + pinctrl-2 = <&mmc2_pins_eint>; + bus-width = <4>; + max-frequency = <200000000>; + cap-sd-highspeed; + sd-uhs-sdr104; + keep-power-in-suspend; + wakeup-source; + cap-sdio-irq; + no-mmc; + no-sd; + non-removable; + vmmc-supply = <&sdio_fixed_3v3>; + vqmmc-supply = <&mt6397_vgp3_reg>; + mmc-pwrseq = <&wifi_pwrseq>; + }; + ... From 019e442bb0d5e7f25ada8eb4252e22e62d17a95e Mon Sep 17 00:00:00 2001 From: Axe Yang Date: Tue, 26 Jul 2022 14:28:41 +0800 Subject: [PATCH 108/111] mmc: core: Add support for SDIO wakeup interrupt If wakeup-source flag is set in host dts node, parse EAI information from SDIO CCCR interrupt externsion segment for in-band wakeup. If async interrupt is supported by SDIO card then enable it and set enable_async_irq flag in sdio_cccr structure to 1. The parse flow is implemented in sdio_read_cccr(). Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Axe Yang Link: https://lore.kernel.org/r/20220726062842.18846-3-axe.yang@mediatek.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/sdio.c | 14 ++++++++++++++ include/linux/mmc/card.h | 8 +++++++- include/linux/mmc/sdio.h | 5 +++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index b589df1c35e0..0b682a31cd3e 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -226,6 +226,20 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr) card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_C; if (data & SDIO_DRIVE_SDTD) card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_D; + + ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTERRUPT_EXT, 0, &data); + if (ret) + goto out; + + if (data & SDIO_INTERRUPT_EXT_SAI) { + data |= SDIO_INTERRUPT_EXT_EAI; + ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_INTERRUPT_EXT, + data, NULL); + if (ret) + goto out; + + card->cccr.enable_async_irq = 1; + } } /* if no uhs mode ensure we check for high speed */ diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 156a7b673a28..8a30de08e913 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -219,7 +219,8 @@ struct sdio_cccr { wide_bus:1, high_power:1, high_speed:1, - disable_cd:1; + disable_cd:1, + enable_async_irq:1; }; struct sdio_cis { @@ -343,6 +344,11 @@ static inline bool mmc_large_sector(struct mmc_card *card) return card->ext_csd.data_sector_size == 4096; } +static inline int mmc_card_enable_async_irq(struct mmc_card *card) +{ + return card->cccr.enable_async_irq; +} + bool mmc_card_is_blockaddr(struct mmc_card *card); #define mmc_card_mmc(c) ((c)->type == MMC_TYPE_MMC) diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h index 2a05d1ac4f0e..1ef400f28642 100644 --- a/include/linux/mmc/sdio.h +++ b/include/linux/mmc/sdio.h @@ -159,6 +159,11 @@ #define SDIO_DTSx_SET_TYPE_A (1 << SDIO_DRIVE_DTSx_SHIFT) #define SDIO_DTSx_SET_TYPE_C (2 << SDIO_DRIVE_DTSx_SHIFT) #define SDIO_DTSx_SET_TYPE_D (3 << SDIO_DRIVE_DTSx_SHIFT) + +#define SDIO_CCCR_INTERRUPT_EXT 0x16 +#define SDIO_INTERRUPT_EXT_SAI (1 << 0) +#define SDIO_INTERRUPT_EXT_EAI (1 << 1) + /* * Function Basic Registers (FBR) */ From 527f36f5efa45b6a897190cabf982e2d207887da Mon Sep 17 00:00:00 2001 From: Axe Yang Date: Tue, 26 Jul 2022 14:28:42 +0800 Subject: [PATCH 109/111] mmc: mediatek: add support for SDIO eint wakup IRQ Add support for eint IRQ when MSDC is used as an SDIO host. This feature requires SDIO device support async IRQ function. With this feature, SDIO host can be awakened by SDIO card in suspend state, without additional pin. MSDC driver will time-share the SDIO DAT1 pin. During suspend, MSDC turn off clock and switch SDIO DAT1 pin to GPIO mode. And during resume, switch GPIO function back to DAT1 mode then turn on clock. Some device tree property should be added or modified in MSDC node to support SDIO eint IRQ. Pinctrls "state_eint" is mandatory. Since this feature depends on asynchronous interrupts, "wakeup-source", "keep-power-in-suspend" and "cap-sdio-irq" flags are necessary, and the interrupts list should be extended(the interrupt named with sdio_wakeup): &mmcX { ... interrupt-names = "msdc", "sdio_wakeup"; interrupts-extended = <...>, <&pio xxx IRQ_TYPE_LEVEL_LOW>; ... pinctrl-names = "default", "state_uhs", "state_eint"; ... pinctrl-2 = <&mmc2_pins_eint>; ... cap-sdio-irq; keep-power-in-suspend; wakeup-source; ... }; Co-developed-by: Yong Mao Signed-off-by: Yong Mao Reviewed-by: Chaotian Jing Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Linus Walleij Signed-off-by: Axe Yang Link: https://lore.kernel.org/r/20220726062842.18846-4-axe.yang@mediatek.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mtk-sd.c | 86 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index a4954b200d87..4ff73d1883de 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2015 MediaTek Inc. + * Copyright (c) 2014-2015, 2022 MediaTek Inc. * Author: Chaotian.Jing */ @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -440,8 +441,10 @@ struct msdc_host { struct pinctrl *pinctrl; struct pinctrl_state *pins_default; struct pinctrl_state *pins_uhs; + struct pinctrl_state *pins_eint; struct delayed_work req_timeout; int irq; /* host interrupt */ + int eint_irq; /* interrupt from sdio device for waking up system */ struct reset_control *reset; struct clk *src_clk; /* msdc source clock */ @@ -1521,17 +1524,46 @@ static void __msdc_enable_sdio_irq(struct msdc_host *host, int enb) static void msdc_enable_sdio_irq(struct mmc_host *mmc, int enb) { - unsigned long flags; struct msdc_host *host = mmc_priv(mmc); + unsigned long flags; + int ret; spin_lock_irqsave(&host->lock, flags); __msdc_enable_sdio_irq(host, enb); spin_unlock_irqrestore(&host->lock, flags); - if (enb) - pm_runtime_get_noresume(host->dev); - else - pm_runtime_put_noidle(host->dev); + if (mmc_card_enable_async_irq(mmc->card) && host->pins_eint) { + if (enb) { + /* + * In dev_pm_set_dedicated_wake_irq_reverse(), eint pin will be set to + * GPIO mode. We need to restore it to SDIO DAT1 mode after that. + * Since the current pinstate is pins_uhs, to ensure pinctrl select take + * affect successfully, we change the pinstate to pins_eint firstly. + */ + pinctrl_select_state(host->pinctrl, host->pins_eint); + ret = dev_pm_set_dedicated_wake_irq_reverse(host->dev, host->eint_irq); + + if (ret) { + dev_err(host->dev, "Failed to register SDIO wakeup irq!\n"); + host->pins_eint = NULL; + pm_runtime_get_noresume(host->dev); + } else { + dev_dbg(host->dev, "SDIO eint irq: %d!\n", host->eint_irq); + } + + pinctrl_select_state(host->pinctrl, host->pins_uhs); + } else { + dev_pm_clear_wake_irq(host->dev); + } + } else { + if (enb) { + /* Ensure host->pins_eint is NULL */ + host->pins_eint = NULL; + pm_runtime_get_noresume(host->dev); + } else { + pm_runtime_put_noidle(host->dev); + } + } } static irqreturn_t msdc_cmdq_irq(struct msdc_host *host, u32 intsts) @@ -2635,6 +2667,20 @@ static int msdc_drv_probe(struct platform_device *pdev) goto host_free; } + /* Support for SDIO eint irq ? */ + if ((mmc->pm_caps & MMC_PM_WAKE_SDIO_IRQ) && (mmc->pm_caps & MMC_PM_KEEP_POWER)) { + host->eint_irq = platform_get_irq_byname(pdev, "sdio_wakeup"); + if (host->eint_irq > 0) { + host->pins_eint = pinctrl_lookup_state(host->pinctrl, "state_eint"); + if (IS_ERR(host->pins_eint)) { + dev_err(&pdev->dev, "Cannot find pinctrl eint!\n"); + host->pins_eint = NULL; + } else { + device_init_wakeup(&pdev->dev, true); + } + } + } + msdc_of_property_parse(pdev, host); host->dev = &pdev->dev; @@ -2849,6 +2895,15 @@ static int __maybe_unused msdc_runtime_suspend(struct device *dev) struct msdc_host *host = mmc_priv(mmc); msdc_save_reg(host); + + if (sdio_irq_claimed(mmc)) { + if (host->pins_eint) { + disable_irq(host->irq); + pinctrl_select_state(host->pinctrl, host->pins_eint); + } + + __msdc_enable_sdio_irq(host, 0); + } msdc_gate_clock(host); return 0; } @@ -2864,12 +2919,18 @@ static int __maybe_unused msdc_runtime_resume(struct device *dev) return ret; msdc_restore_reg(host); + + if (sdio_irq_claimed(mmc) && host->pins_eint) { + pinctrl_select_state(host->pinctrl, host->pins_uhs); + enable_irq(host->irq); + } return 0; } static int __maybe_unused msdc_suspend(struct device *dev) { struct mmc_host *mmc = dev_get_drvdata(dev); + struct msdc_host *host = mmc_priv(mmc); int ret; if (mmc->caps2 & MMC_CAP2_CQE) { @@ -2878,11 +2939,24 @@ static int __maybe_unused msdc_suspend(struct device *dev) return ret; } + /* + * Bump up runtime PM usage counter otherwise dev->power.needs_force_resume will + * not be marked as 1, pm_runtime_force_resume() will go out directly. + */ + if (sdio_irq_claimed(mmc) && host->pins_eint) + pm_runtime_get_noresume(dev); + return pm_runtime_force_suspend(dev); } static int __maybe_unused msdc_resume(struct device *dev) { + struct mmc_host *mmc = dev_get_drvdata(dev); + struct msdc_host *host = mmc_priv(mmc); + + if (sdio_irq_claimed(mmc) && host->pins_eint) + pm_runtime_put_noidle(dev); + return pm_runtime_force_resume(dev); } From 9327c7e7539371c6f202303d5539afbae006ec72 Mon Sep 17 00:00:00 2001 From: Mathias Tausen Date: Tue, 26 Jul 2022 16:02:12 +0200 Subject: [PATCH 110/111] 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; From a1873f837f9e5c1001462a635af1b0bab31aa9fd Mon Sep 17 00:00:00 2001 From: Slark Xiao Date: Thu, 21 Jul 2022 13:56:47 +0800 Subject: [PATCH 111/111] 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