aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml20
-rw-r--r--Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml31
-rw-r--r--Documentation/devicetree/bindings/mmc/marvell,dove-sdhci.yaml44
-rw-r--r--Documentation/devicetree/bindings/mmc/marvell,orion-sdio.yaml44
-rw-r--r--Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt173
-rw-r--r--Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml275
-rw-r--r--Documentation/devicetree/bindings/mmc/mmc-controller.yaml5
-rw-r--r--Documentation/devicetree/bindings/mmc/mtk-sd.yaml15
-rw-r--r--Documentation/devicetree/bindings/mmc/orion-sdio.txt16
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-am654.yaml7
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-dove.txt14
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-msm.txt123
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-msm.yaml194
-rw-r--r--Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml1
-rw-r--r--MAINTAINERS3
-rw-r--r--arch/sh/boards/board-sh7757lcr.c2
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c2
-rw-r--r--arch/sh/boot/romimage/mmcif-sh7724.c2
-rw-r--r--drivers/mmc/core/block.c52
-rw-r--r--drivers/mmc/core/core.c7
-rw-r--r--drivers/mmc/core/mmc.c11
-rw-r--r--drivers/mmc/core/queue.c2
-rw-r--r--drivers/mmc/core/sd.c7
-rw-r--r--drivers/mmc/host/atmel-mci.c9
-rw-r--r--drivers/mmc/host/bcm2835.c2
-rw-r--r--drivers/mmc/host/dw_mmc.c2
-rw-r--r--drivers/mmc/host/jz4740_mmc.c20
-rw-r--r--drivers/mmc/host/meson-gx-mmc.c21
-rw-r--r--drivers/mmc/host/meson-mx-sdhc-mmc.c2
-rw-r--r--drivers/mmc/host/mmci.c6
-rw-r--r--drivers/mmc/host/mmci_stm32_sdmmc.c88
-rw-r--r--drivers/mmc/host/mtk-sd.c2
-rw-r--r--drivers/mmc/host/of_mmc_spi.c4
-rw-r--r--drivers/mmc/host/omap.c23
-rw-r--r--drivers/mmc/host/renesas_sdhi.h2
-rw-r--r--drivers/mmc/host/renesas_sdhi_core.c2
-rw-r--r--drivers/mmc/host/renesas_sdhi_internal_dmac.c76
-rw-r--r--drivers/mmc/host/sdhci-brcmstb.c67
-rw-r--r--drivers/mmc/host/sdhci-msm.c25
-rw-r--r--drivers/mmc/host/sdhci-of-arasan.c3
-rw-r--r--drivers/mmc/host/sdhci-omap.c9
-rw-r--r--drivers/mmc/host/sdhci-pci-gli.c10
-rw-r--r--drivers/mmc/host/sdhci.c2
-rw-r--r--drivers/mmc/host/sdhci_am654.c23
-rw-r--r--drivers/mmc/host/sh_mmcif.c2
-rw-r--r--drivers/mmc/host/sunxi-mmc.c2
-rw-r--r--drivers/mmc/host/uniphier-sd.c2
-rw-r--r--include/linux/amba/mmci.h6
-rw-r--r--include/linux/mmc/core.h2
-rw-r--r--include/linux/mmc/host.h2
-rw-r--r--include/linux/platform_data/sh_mmcif.h (renamed from include/linux/mmc/sh_mmcif.h)2
51 files changed, 963 insertions, 503 deletions
diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
index dccd5ad96981..b672202fff4e 100644
--- a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
+++ b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml
@@ -31,7 +31,7 @@ properties:
- const: brcm,sdhci-brcmstb
reg:
- minItems: 2
+ maxItems: 2
reg-names:
items:
@@ -65,15 +65,15 @@ unevaluatedProperties: false
examples:
- |
mmc@84b0000 {
- sd-uhs-sdr50;
- sd-uhs-ddr50;
- sd-uhs-sdr104;
- sdhci,auto-cmd12;
compatible = "brcm,bcm7216-sdhci",
"brcm,bcm7445-sdhci",
"brcm,sdhci-brcmstb";
reg = <0x84b0000 0x260>, <0x84b0300 0x200>;
reg-names = "host", "cfg";
+ sd-uhs-sdr50;
+ sd-uhs-ddr50;
+ sd-uhs-sdr104;
+ sdhci,auto-cmd12;
interrupts = <0x0 0x26 0x4>;
interrupt-names = "sdio0_0";
clocks = <&scmi_clk 245>;
@@ -81,6 +81,11 @@ examples:
};
mmc@84b1000 {
+ compatible = "brcm,bcm7216-sdhci",
+ "brcm,bcm7445-sdhci",
+ "brcm,sdhci-brcmstb";
+ reg = <0x84b1000 0x260>, <0x84b1300 0x200>;
+ reg-names = "host", "cfg";
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
@@ -88,11 +93,6 @@ examples:
supports-cqe;
non-removable;
bus-width = <0x8>;
- compatible = "brcm,bcm7216-sdhci",
- "brcm,bcm7445-sdhci",
- "brcm,sdhci-brcmstb";
- reg = <0x84b1000 0x260>, <0x84b1300 0x200>;
- reg-names = "host", "cfg";
interrupts = <0x0 0x27 0x4>;
interrupt-names = "sdio1_0";
clocks = <&scmi_clk 245>;
diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
index 7dbbcae9485c..29339d0196ec 100644
--- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
+++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
@@ -34,22 +34,47 @@ properties:
- fsl,imx6ull-usdhc
- fsl,imx7d-usdhc
- fsl,imx7ulp-usdhc
+ - fsl,imx8mm-usdhc
- fsl,imxrt1050-usdhc
- nxp,s32g2-usdhc
- items:
- enum:
+ - fsl,imx8mq-usdhc
+ - const: fsl,imx7d-usdhc
+ - items:
+ - enum:
+ - fsl,imx8mn-usdhc
+ - fsl,imx8mp-usdhc
+ - fsl,imx93-usdhc
+ - fsl,imx8ulp-usdhc
+ - const: fsl,imx8mm-usdhc
+ - items:
+ - enum:
+ - fsl,imx8qm-usdhc
+ - const: fsl,imx8qxp-usdhc
+ - items:
+ - enum:
+ - fsl,imx8dxl-usdhc
- fsl,imx8mm-usdhc
- fsl,imx8mn-usdhc
- fsl,imx8mp-usdhc
- - fsl,imx8mq-usdhc
- fsl,imx8qm-usdhc
- fsl,imx8qxp-usdhc
- const: fsl,imx7d-usdhc
+ deprecated: true
- items:
- enum:
- - fsl,imx93-usdhc
- - fsl,imx8ulp-usdhc
+ - fsl,imx8mn-usdhc
+ - fsl,imx8mp-usdhc
- const: fsl,imx8mm-usdhc
+ - const: fsl,imx7d-usdhc
+ deprecated: true
+ - items:
+ - enum:
+ - fsl,imx8qm-usdhc
+ - const: fsl,imx8qxp-usdhc
+ - const: fsl,imx7d-usdhc
+ deprecated: true
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/mmc/marvell,dove-sdhci.yaml b/Documentation/devicetree/bindings/mmc/marvell,dove-sdhci.yaml
new file mode 100644
index 000000000000..7c9c652ad59c
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/marvell,dove-sdhci.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/marvell,dove-sdhci.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell sdhci-dove controller
+
+maintainers:
+ - Adrian Hunter <adrian.hunter@intel.com>
+ - Ulf Hansson <ulf.hansson@linaro.org>
+
+allOf:
+ - $ref: mmc-controller.yaml#
+
+properties:
+ compatible:
+ const: marvell,dove-sdhci
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ minItems: 1
+ maxItems: 2
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ sdio0: mmc@92000 {
+ compatible = "marvell,dove-sdhci";
+ reg = <0x92000 0x100>;
+ interrupts = <35>;
+ clocks = <&gate_clk 9>;
+ };
diff --git a/Documentation/devicetree/bindings/mmc/marvell,orion-sdio.yaml b/Documentation/devicetree/bindings/mmc/marvell,orion-sdio.yaml
new file mode 100644
index 000000000000..8a97ded15aed
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/marvell,orion-sdio.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/marvell,orion-sdio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell orion-sdio controller
+
+maintainers:
+ - Nicolas Pitre <nico@fluxnic.net>
+ - Ulf Hansson <ulf.hansson@linaro.org>
+
+allOf:
+ - $ref: mmc-controller.yaml#
+
+properties:
+ compatible:
+ const: marvell,orion-sdio
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ mmc@d00d4000 {
+ compatible = "marvell,orion-sdio";
+ reg = <0xd00d4000 0x200>;
+ interrupts = <54>;
+ clocks = <&gateclk 17>;
+ };
diff --git a/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt b/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt
deleted file mode 100644
index c51a62d751dc..000000000000
--- a/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt
+++ /dev/null
@@ -1,173 +0,0 @@
-Marvell Xenon SDHCI Controller device tree bindings
-This file documents differences between the core mmc properties
-described by mmc.txt and the properties used by the Xenon implementation.
-
-Multiple SDHCs might be put into a single Xenon IP, to save size and cost.
-Each SDHC is independent and owns independent resources, such as register sets,
-clock and PHY.
-Each SDHC should have an independent device tree node.
-
-Required Properties:
-- compatible: should be one of the following
- - "marvell,armada-3700-sdhci": For controllers on Armada-3700 SoC.
- Must provide a second register area and marvell,pad-type.
- - "marvell,armada-ap806-sdhci": For controllers on Armada AP806.
- - "marvell,armada-ap807-sdhci": For controllers on Armada AP807.
- - "marvell,armada-cp110-sdhci": For controllers on Armada CP110.
-
-- clocks:
- Array of clocks required for SDHC.
- Require at least input clock for Xenon IP core. For Armada AP806 and
- CP110, the AXI clock is also mandatory.
-
-- clock-names:
- Array of names corresponding to clocks property.
- The input clock for Xenon IP core should be named as "core".
- The input clock for the AXI bus must be named as "axi".
-
-- reg:
- * For "marvell,armada-3700-sdhci", two register areas.
- The first one for Xenon IP register. The second one for the Armada 3700 SoC
- PHY PAD Voltage Control register.
- Please follow the examples with compatible "marvell,armada-3700-sdhci"
- in below.
- Please also check property marvell,pad-type in below.
-
- * For other compatible strings, one register area for Xenon IP.
-
-Optional Properties:
-- marvell,xenon-sdhc-id:
- Indicate the corresponding bit index of current SDHC in
- SDHC System Operation Control Register Bit[7:0].
- Set/clear the corresponding bit to enable/disable current SDHC.
- If Xenon IP contains only one SDHC, this property is optional.
-
-- marvell,xenon-phy-type:
- Xenon support multiple types of PHYs.
- To select eMMC 5.1 PHY, set:
- marvell,xenon-phy-type = "emmc 5.1 phy"
- eMMC 5.1 PHY is the default choice if this property is not provided.
- To select eMMC 5.0 PHY, set:
- marvell,xenon-phy-type = "emmc 5.0 phy"
-
- All those types of PHYs can support eMMC, SD and SDIO.
- Please note that this property only presents the type of PHY.
- It doesn't stand for the entire SDHC type or property.
- For example, "emmc 5.1 phy" doesn't mean that this Xenon SDHC only
- supports eMMC 5.1.
-
-- marvell,xenon-phy-znr:
- Set PHY ZNR value.
- Only available for eMMC PHY.
- Valid range = [0:0x1F].
- ZNR is set as 0xF by default if this property is not provided.
-
-- marvell,xenon-phy-zpr:
- Set PHY ZPR value.
- Only available for eMMC PHY.
- Valid range = [0:0x1F].
- ZPR is set as 0xF by default if this property is not provided.
-
-- marvell,xenon-phy-nr-success-tun:
- Set the number of required consecutive successful sampling points
- used to identify a valid sampling window, in tuning process.
- Valid range = [1:7].
- Set as 0x4 by default if this property is not provided.
-
-- marvell,xenon-phy-tun-step-divider:
- Set the divider for calculating TUN_STEP.
- Set as 64 by default if this property is not provided.
-
-- marvell,xenon-phy-slow-mode:
- If this property is selected, transfers will bypass PHY.
- Only available when bus frequency lower than 55MHz in SDR mode.
- Disabled by default. Please only try this property if timing issues
- always occur with PHY enabled in eMMC HS SDR, SD SDR12, SD SDR25,
- SD Default Speed and HS mode and eMMC legacy speed mode.
-
-- marvell,xenon-tun-count:
- Xenon SDHC SoC usually doesn't provide re-tuning counter in
- Capabilities Register 3 Bit[11:8].
- This property provides the re-tuning counter.
- If this property is not set, default re-tuning counter will
- be set as 0x9 in driver.
-
-- marvell,pad-type:
- Type of Armada 3700 SoC PHY PAD Voltage Controller register.
- Only valid when "marvell,armada-3700-sdhci" is selected.
- Two types: "sd" and "fixed-1-8v".
- If "sd" is selected, SoC PHY PAD is set as 3.3V at the beginning and is
- switched to 1.8V when later in higher speed mode.
- If "fixed-1-8v" is selected, SoC PHY PAD is fixed 1.8V, such as for eMMC.
- Please follow the examples with compatible "marvell,armada-3700-sdhci"
- in below.
-
-Example:
-- For eMMC:
-
- sdhci@aa0000 {
- compatible = "marvell,armada-ap806-sdhci";
- reg = <0xaa0000 0x1000>;
- interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>
- clocks = <&emmc_clk>,<&axi_clk>;
- clock-names = "core", "axi";
- bus-width = <4>;
- marvell,xenon-phy-slow-mode;
- marvell,xenon-tun-count = <11>;
- non-removable;
- no-sd;
- no-sdio;
-
- /* Vmmc and Vqmmc are both fixed */
- };
-
-- For SD/SDIO:
-
- sdhci@ab0000 {
- compatible = "marvell,armada-cp110-sdhci";
- reg = <0xab0000 0x1000>;
- interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>
- vqmmc-supply = <&sd_vqmmc_regulator>;
- vmmc-supply = <&sd_vmmc_regulator>;
- clocks = <&sdclk>, <&axi_clk>;
- clock-names = "core", "axi";
- bus-width = <4>;
- marvell,xenon-tun-count = <9>;
- };
-
-- For eMMC with compatible "marvell,armada-3700-sdhci":
-
- sdhci@aa0000 {
- compatible = "marvell,armada-3700-sdhci";
- reg = <0xaa0000 0x1000>,
- <phy_addr 0x4>;
- interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>
- clocks = <&emmcclk>;
- clock-names = "core";
- bus-width = <8>;
- mmc-ddr-1_8v;
- mmc-hs400-1_8v;
- non-removable;
- no-sd;
- no-sdio;
-
- /* Vmmc and Vqmmc are both fixed */
-
- marvell,pad-type = "fixed-1-8v";
- };
-
-- For SD/SDIO with compatible "marvell,armada-3700-sdhci":
-
- sdhci@ab0000 {
- compatible = "marvell,armada-3700-sdhci";
- reg = <0xab0000 0x1000>,
- <phy_addr 0x4>;
- interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>
- vqmmc-supply = <&sd_regulator>;
- /* Vmmc is fixed */
- clocks = <&sdclk>;
- clock-names = "core";
- bus-width = <4>;
-
- marvell,pad-type = "sd";
- };
diff --git a/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml b/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml
new file mode 100644
index 000000000000..c79639e9027e
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml
@@ -0,0 +1,275 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/marvell,xenon-sdhci.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell Xenon SDHCI Controller
+
+description: |
+ This file documents differences between the core MMC properties described by
+ mmc-controller.yaml and the properties used by the Xenon implementation.
+
+ Multiple SDHCs might be put into a single Xenon IP, to save size and cost.
+ Each SDHC is independent and owns independent resources, such as register
+ sets, clock and PHY.
+
+ Each SDHC should have an independent device tree node.
+
+maintainers:
+ - Ulf Hansson <ulf.hansson@linaro.org>
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - marvell,armada-cp110-sdhci
+ - marvell,armada-ap806-sdhci
+
+ - items:
+ - const: marvell,armada-ap807-sdhci
+ - const: marvell,armada-ap806-sdhci
+
+ - items:
+ - const: marvell,armada-3700-sdhci
+ - const: marvell,sdhci-xenon
+
+ reg:
+ minItems: 1
+ maxItems: 2
+ description: |
+ For "marvell,armada-3700-sdhci", two register areas. The first one
+ for Xenon IP register. The second one for the Armada 3700 SoC PHY PAD
+ Voltage Control register. Please follow the examples with compatible
+ "marvell,armada-3700-sdhci" in below.
+ Please also check property marvell,pad-type in below.
+
+ For other compatible strings, one register area for Xenon IP.
+
+ clocks:
+ minItems: 1
+ maxItems: 2
+
+ clock-names:
+ minItems: 1
+ items:
+ - const: core
+ - const: axi
+
+ marvell,xenon-sdhc-id:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 7
+ description: |
+ Indicate the corresponding bit index of current SDHC in SDHC System
+ Operation Control Register Bit[7:0]. Set/clear the corresponding bit to
+ enable/disable current SDHC.
+
+ marvell,xenon-phy-type:
+ $ref: /schemas/types.yaml#/definitions/string
+ enum:
+ - "emmc 5.1 phy"
+ - "emmc 5.0 phy"
+ description: |
+ Xenon support multiple types of PHYs. To select eMMC 5.1 PHY, set:
+ marvell,xenon-phy-type = "emmc 5.1 phy" eMMC 5.1 PHY is the default
+ choice if this property is not provided. To select eMMC 5.0 PHY, set:
+ marvell,xenon-phy-type = "emmc 5.0 phy"
+
+ All those types of PHYs can support eMMC, SD and SDIO. Please note that
+ this property only presents the type of PHY. It doesn't stand for the
+ entire SDHC type or property. For example, "emmc 5.1 phy" doesn't mean
+ that this Xenon SDHC only supports eMMC 5.1.
+
+ marvell,xenon-phy-znr:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 0x1f
+ default: 0xf
+ description: |
+ Set PHY ZNR value.
+ Only available for eMMC PHY.
+
+ marvell,xenon-phy-zpr:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 0x1f
+ default: 0xf
+ description: |
+ Set PHY ZPR value.
+ Only available for eMMC PHY.
+
+ marvell,xenon-phy-nr-success-tun:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 1
+ maximum: 7
+ default: 0x4
+ description: |
+ Set the number of required consecutive successful sampling points
+ used to identify a valid sampling window, in tuning process.
+
+ marvell,xenon-phy-tun-step-divider:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 64
+ description: |
+ Set the divider for calculating TUN_STEP.
+
+ marvell,xenon-phy-slow-mode:
+ type: boolean
+ description: |
+ If this property is selected, transfers will bypass PHY.
+ Only available when bus frequency lower than 55MHz in SDR mode.
+ Disabled by default. Please only try this property if timing issues
+ always occur with PHY enabled in eMMC HS SDR, SD SDR12, SD SDR25,
+ SD Default Speed and HS mode and eMMC legacy speed mode.
+
+ marvell,xenon-tun-count:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0x9
+ description: |
+ Xenon SDHC SoC usually doesn't provide re-tuning counter in
+ Capabilities Register 3 Bit[11:8].
+ This property provides the re-tuning counter.
+
+allOf:
+ - $ref: mmc-controller.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: marvell,armada-3700-sdhci
+
+ then:
+ properties:
+ reg:
+ items:
+ - description: Xenon IP registers
+ - description: Armada 3700 SoC PHY PAD Voltage Control register
+ minItems: 2
+
+ marvell,pad-type:
+ $ref: /schemas/types.yaml#/definitions/string
+ enum:
+ - sd
+ - fixed-1-8v
+ description: |
+ Type of Armada 3700 SoC PHY PAD Voltage Controller register.
+ If "sd" is selected, SoC PHY PAD is set as 3.3V at the beginning
+ and is switched to 1.8V when later in higher speed mode.
+ If "fixed-1-8v" is selected, SoC PHY PAD is fixed 1.8V, such as for
+ eMMC.
+ Please follow the examples with compatible
+ "marvell,armada-3700-sdhci" in below.
+
+ required:
+ - marvell,pad-type
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - marvell,armada-cp110-sdhci
+ - marvell,armada-ap807-sdhci
+ - marvell,armada-ap806-sdhci
+
+ then:
+ properties:
+ clocks:
+ minItems: 2
+
+ clock-names:
+ items:
+ - const: core
+ - const: axi
+
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ // For eMMC
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ mmc@aa0000 {
+ compatible = "marvell,armada-ap807-sdhci", "marvell,armada-ap806-sdhci";
+ reg = <0xaa0000 0x1000>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&emmc_clk 0>, <&axi_clk 0>;
+ clock-names = "core", "axi";
+ bus-width = <4>;
+ marvell,xenon-phy-slow-mode;
+ marvell,xenon-tun-count = <11>;
+ non-removable;
+ no-sd;
+ no-sdio;
+
+ /* Vmmc and Vqmmc are both fixed */
+ };
+
+ - |
+ // For SD/SDIO
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ mmc@ab0000 {
+ compatible = "marvell,armada-cp110-sdhci";
+ reg = <0xab0000 0x1000>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ vqmmc-supply = <&sd_vqmmc_regulator>;
+ vmmc-supply = <&sd_vmmc_regulator>;
+ clocks = <&sdclk 0>, <&axi_clk 0>;
+ clock-names = "core", "axi";
+ bus-width = <4>;
+ marvell,xenon-tun-count = <9>;
+ };
+
+ - |
+ // For eMMC with compatible "marvell,armada-3700-sdhci":
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ mmc@aa0000 {
+ compatible = "marvell,armada-3700-sdhci", "marvell,sdhci-xenon";
+ reg = <0xaa0000 0x1000>,
+ <0x17808 0x4>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&emmcclk 0>;
+ clock-names = "core";
+ bus-width = <8>;
+ mmc-ddr-1_8v;
+ mmc-hs400-1_8v;
+ non-removable;
+ no-sd;
+ no-sdio;
+
+ /* Vmmc and Vqmmc are both fixed */
+
+ marvell,pad-type = "fixed-1-8v";
+ };
+
+ - |
+ // For SD/SDIO with compatible "marvell,armada-3700-sdhci":
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ mmc@ab0000 {
+ compatible = "marvell,armada-3700-sdhci", "marvell,sdhci-xenon";
+ reg = <0xab0000 0x1000>,
+ <0x17808 0x4>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ vqmmc-supply = <&sd_regulator>;
+ /* Vmmc is fixed */
+ clocks = <&sdclk 0>;
+ clock-names = "core";
+ bus-width = <4>;
+
+ marvell,pad-type = "sd";
+ };
diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml
index 513f3c8758aa..ff5ce89e5111 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml
+++ b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml
@@ -298,7 +298,10 @@ properties:
vqmmc-supply:
description:
- Supply for the bus IO line power
+ Supply for the bus IO line power, such as a level shifter.
+ If the level shifter is controlled by a GPIO line, this shall
+ be modeled as a "regulator-fixed" with a GPIO line for
+ switching the level shifter on/off.
mmc-pwrseq:
$ref: /schemas/types.yaml#/definitions/phandle
diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
index 297ada03e3de..2a2e9fa8c188 100644
--- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
+++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
@@ -40,7 +40,10 @@ properties:
- const: mediatek,mt8183-mmc
reg:
- maxItems: 1
+ minItems: 1
+ items:
+ - description: base register (required).
+ - description: top base register (required for MT8183).
clocks:
description:
@@ -168,6 +171,16 @@ required:
- vmmc-supply
- vqmmc-supply
+if:
+ properties:
+ compatible:
+ contains:
+ const: mediatek,mt8183-mmc
+then:
+ properties:
+ reg:
+ minItems: 2
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/mmc/orion-sdio.txt b/Documentation/devicetree/bindings/mmc/orion-sdio.txt
deleted file mode 100644
index 10f0818a34c5..000000000000
--- a/Documentation/devicetree/bindings/mmc/orion-sdio.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-* Marvell orion-sdio controller
-
-This file documents differences between the core properties in mmc.txt
-and the properties used by the orion-sdio driver.
-
-- compatible: Should be "marvell,orion-sdio"
-- clocks: reference to the clock of the SDIO interface
-
-Example:
-
- mvsdio@d00d4000 {
- compatible = "marvell,orion-sdio";
- reg = <0xd00d4000 0x200>;
- interrupts = <54>;
- clocks = <&gateclk 17>;
- };
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml
index 0566493c4def..0ab07759b472 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml
+++ b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml
@@ -186,6 +186,13 @@ properties:
description: Clock Delay Buffer Select
$ref: "/schemas/types.yaml#/definitions/uint32"
+ ti,fails-without-test-cd:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ When present, indicates that the CD line is not connected
+ and the controller is required to be forced into Test mode
+ to set the TESTCD bit.
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-dove.txt b/Documentation/devicetree/bindings/mmc/sdhci-dove.txt
deleted file mode 100644
index ae9aab9abcd7..000000000000
--- a/Documentation/devicetree/bindings/mmc/sdhci-dove.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-* Marvell sdhci-dove controller
-
-This file documents differences between the core properties in mmc.txt
-and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers.
-
-- compatible: Should be "marvell,dove-sdhci".
-
-Example:
-
-sdio0: sdio@92000 {
- compatible = "marvell,dove-sdhci";
- reg = <0x92000 0x100>;
- interrupts = <35>;
-};
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
deleted file mode 100644
index 6216ed777343..000000000000
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ /dev/null
@@ -1,123 +0,0 @@
-* Qualcomm SDHCI controller (sdhci-msm)
-
-This file documents differences between the core properties in mmc.txt
-and the properties used by the sdhci-msm driver.
-
-Required properties:
-- compatible: Should contain a SoC-specific string and a IP version string:
- version strings:
- "qcom,sdhci-msm-v4" for sdcc versions less than 5.0
- "qcom,sdhci-msm-v5" for sdcc version 5.0
- For SDCC version 5.0.0, MCI registers are removed from SDCC
- interface and some registers are moved to HC. New compatible
- string is added to support this change - "qcom,sdhci-msm-v5".
- full compatible strings with SoC and version:
- "qcom,apq8084-sdhci", "qcom,sdhci-msm-v4"
- "qcom,msm8226-sdhci", "qcom,sdhci-msm-v4"
- "qcom,msm8953-sdhci", "qcom,sdhci-msm-v4"
- "qcom,msm8974-sdhci", "qcom,sdhci-msm-v4"
- "qcom,msm8916-sdhci", "qcom,sdhci-msm-v4"
- "qcom,msm8992-sdhci", "qcom,sdhci-msm-v4"
- "qcom,msm8994-sdhci", "qcom,sdhci-msm-v4"
- "qcom,msm8996-sdhci", "qcom,sdhci-msm-v4"
- "qcom,qcs404-sdhci", "qcom,sdhci-msm-v5"
- "qcom,sc7180-sdhci", "qcom,sdhci-msm-v5";
- "qcom,sc7280-sdhci", "qcom,sdhci-msm-v5";
- "qcom,sdm845-sdhci", "qcom,sdhci-msm-v5"
- "qcom,sdx55-sdhci", "qcom,sdhci-msm-v5";
- "qcom,sm8250-sdhci", "qcom,sdhci-msm-v5"
- NOTE that some old device tree files may be floating around that only
- have the string "qcom,sdhci-msm-v4" without the SoC compatible string
- but doing that should be considered a deprecated practice.
-
-- reg: Base address and length of the register in the following order:
- - Host controller register map (required)
- - SD Core register map (required for controllers earlier than msm-v5)
- - CQE register map (Optional, CQE support is present on SDHC instance meant
- for eMMC and version v4.2 and above)
- - Inline Crypto Engine register map (optional)
-- reg-names: When CQE register map is supplied, below reg-names are required
- - "hc" for Host controller register map
- - "core" for SD core register map
- - "cqhci" for CQE register map
- - "ice" for Inline Crypto Engine register map (optional)
-- interrupts: Should contain an interrupt-specifiers for the interrupts:
- - Host controller interrupt (required)
-- pinctrl-names: Should contain only one value - "default".
-- pinctrl-0: Should specify pin control groups used for this controller.
-- clocks: A list of phandle + clock-specifier pairs for the clocks listed in clock-names.
-- clock-names: Should contain the following:
- "iface" - Main peripheral bus clock (PCLK/HCLK - AHB Bus clock) (required)
- "core" - SDC MMC clock (MCLK) (required)
- "bus" - SDCC bus voter clock (optional)
- "xo" - TCXO clock (optional)
- "cal" - reference clock for RCLK delay calibration (optional)
- "sleep" - sleep clock for RCLK delay calibration (optional)
- "ice" - clock for Inline Crypto Engine (optional)
-
-- qcom,ddr-config: Certain chipsets and platforms require particular settings
- for the DDR_CONFIG register. Use this field to specify the register
- value as per the Hardware Programming Guide.
-
-- qcom,dll-config: Chipset and Platform specific value. Use this field to
- specify the DLL_CONFIG register value as per Hardware Programming Guide.
-
-Optional Properties:
-* Following bus parameters are required for interconnect bandwidth scaling:
-- interconnects: Pairs of phandles and interconnect provider specifier
- to denote the edge source and destination ports of
- the interconnect path.
-
-- interconnect-names: For sdhc, we have two main paths.
- 1. Data path : sdhc to ddr
- 2. Config path : cpu to sdhc
- For Data interconnect path the name supposed to be
- is "sdhc-ddr" and for config interconnect path it is
- "cpu-sdhc".
- Please refer to Documentation/devicetree/bindings/
- interconnect/ for more details.
-
-Example:
-
- sdhc_1: sdhci@f9824900 {
- compatible = "qcom,msm8974-sdhci", "qcom,sdhci-msm-v4";
- reg = <0xf9824900 0x11c>, <0xf9824000 0x800>;
- interrupts = <0 123 0>;
- bus-width = <8>;
- non-removable;
-
- vmmc-supply = <&pm8941_l20>;
- vqmmc-supply = <&pm8941_s3>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&sdc1_clk &sdc1_cmd &sdc1_data>;
-
- clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>;
- clock-names = "core", "iface";
- interconnects = <&qnoc MASTER_SDCC_ID &qnoc SLAVE_DDR_ID>,
- <&qnoc MASTER_CPU_ID &qnoc SLAVE_SDCC_ID>;
- interconnect-names = "sdhc-ddr","cpu-sdhc";
-
- qcom,dll-config = <0x000f642c>;
- qcom,ddr-config = <0x80040868>;
- };
-
- sdhc_2: sdhci@f98a4900 {
- compatible = "qcom,msm8974-sdhci", "qcom,sdhci-msm-v4";
- reg = <0xf98a4900 0x11c>, <0xf98a4000 0x800>;
- interrupts = <0 125 0>;
- bus-width = <4>;
- cd-gpios = <&msmgpio 62 0x1>;
-
- vmmc-supply = <&pm8941_l21>;
- vqmmc-supply = <&pm8941_l13>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&sdc2_clk &sdc2_cmd &sdc2_data>;
-
- clocks = <&gcc GCC_SDCC2_APPS_CLK>, <&gcc GCC_SDCC2_AHB_CLK>;
- clock-names = "core", "iface";
-
- qcom,dll-config = <0x0007642c>;
- qcom,ddr-config = <0x80040868>;
- };
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
new file mode 100644
index 000000000000..e4236334e748
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
@@ -0,0 +1,194 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/mmc/sdhci-msm.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Qualcomm SDHCI controller (sdhci-msm)
+
+maintainers:
+ - Bhupesh Sharma <bhupesh.sharma@linaro.org>
+
+description:
+ Secure Digital Host Controller Interface (SDHCI) present on
+ Qualcomm SOCs supports SD/MMC/SDIO devices.
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - qcom,apq8084-sdhci
+ - qcom,msm8226-sdhci
+ - qcom,msm8953-sdhci
+ - qcom,msm8974-sdhci
+ - qcom,msm8916-sdhci
+ - qcom,msm8992-sdhci
+ - qcom,msm8994-sdhci
+ - qcom,msm8996-sdhci
+ - qcom,qcs404-sdhci
+ - qcom,sc7180-sdhci
+ - qcom,sc7280-sdhci
+ - qcom,sdm630-sdhci
+ - qcom,sdm845-sdhci
+ - qcom,sdx55-sdhci
+ - qcom,sdx65-sdhci
+ - qcom,sm6125-sdhci
+ - 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
+
+ reg:
+ minItems: 1
+ items:
+ - description: Host controller register map
+ - description: SD Core register map
+ - description: CQE register map
+ - description: Inline Crypto Engine register map
+
+ clocks:
+ minItems: 3
+ items:
+ - description: Main peripheral bus clock, PCLK/HCLK - AHB Bus clock
+ - description: SDC MMC clock, MCLK
+ - description: TCXO clock
+ - description: clock for Inline Crypto Engine
+ - description: SDCC bus voter clock
+ - description: reference clock for RCLK delay calibration
+ - description: sleep clock for RCLK delay calibration
+
+ clock-names:
+ minItems: 2
+ items:
+ - const: iface
+ - const: core
+ - const: xo
+ - const: ice
+ - const: bus
+ - const: cal
+ - const: sleep
+
+ interrupts:
+ maxItems: 2
+
+ interrupt-names:
+ items:
+ - const: hc_irq
+ - const: pwr_irq
+
+ pinctrl-names:
+ minItems: 1
+ items:
+ - const: default
+ - const: sleep
+
+ pinctrl-0:
+ description:
+ Should specify pin control groups used for this controller.
+
+ qcom,ddr-config:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: platform specific settings for DDR_CONFIG reg.
+
+ qcom,dll-config:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: platform specific settings for DLL_CONFIG reg.
+
+ iommus:
+ minItems: 1
+ maxItems: 8
+ description: |
+ phandle to apps_smmu node with sid mask.
+
+ interconnects:
+ items:
+ - description: data path, sdhc to ddr
+ - description: config path, cpu to sdhc
+
+ interconnect-names:
+ items:
+ - const: sdhc-ddr
+ - const: cpu-sdhc
+
+ power-domains:
+ description: A phandle to sdhci power domain node
+ maxItems: 1
+
+patternProperties:
+ '^opp-table(-[a-z0-9]+)?$':
+ if:
+ properties:
+ compatible:
+ const: operating-points-v2
+ then:
+ patternProperties:
+ '^opp-?[0-9]+$':
+ required:
+ - required-opps
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - interrupts
+
+additionalProperties: true
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/qcom,gcc-sm8250.h>
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ sdhc_2: sdhci@8804000 {
+ compatible = "qcom,sm8250-sdhci", "qcom,sdhci-msm-v5";
+ reg = <0 0x08804000 0 0x1000>;
+
+ interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC2_AHB_CLK>,
+ <&gcc GCC_SDCC2_APPS_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "core", "xo";
+ iommus = <&apps_smmu 0x4a0 0x0>;
+ qcom,dll-config = <0x0007642c>;
+ qcom,ddr-config = <0x80040868>;
+ power-domains = <&rpmhpd SM8250_CX>;
+
+ operating-points-v2 = <&sdhc2_opp_table>;
+
+ sdhc2_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-19200000 {
+ opp-hz = /bits/ 64 <19200000>;
+ required-opps = <&rpmhpd_opp_min_svs>;
+ };
+
+ opp-50000000 {
+ opp-hz = /bits/ 64 <50000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-202000000 {
+ opp-hz = /bits/ 64 <202000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
index f300ced4cdf3..71f8e726d641 100644
--- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
@@ -17,6 +17,7 @@ properties:
compatible:
enum:
- rockchip,rk3568-dwcmshc
+ - rockchip,rk3588-dwcmshc
- snps,dwcmshc-sdhci
reg:
diff --git a/MAINTAINERS b/MAINTAINERS
index 65e5fe38c9a1..1ac45caa2dcd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11849,7 +11849,7 @@ MARVELL XENON MMC/SD/SDIO HOST CONTROLLER DRIVER
M: Hu Ziji <huziji@marvell.com>
L: linux-mmc@vger.kernel.org
S: Supported
-F: Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt
+F: Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml
F: drivers/mmc/host/sdhci-xenon*
MATROX FRAMEBUFFER DRIVER
@@ -19871,6 +19871,7 @@ F: drivers/media/usb/tm6000/
TMIO/SDHI MMC DRIVER
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
L: linux-mmc@vger.kernel.org
+L: linux-renesas-soc@vger.kernel.org
S: Supported
F: drivers/mmc/host/renesas_sdhi*
F: drivers/mmc/host/tmio_mmc*
diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c
index c32b4c6229d3..f39c8196efdf 100644
--- a/arch/sh/boards/board-sh7757lcr.c
+++ b/arch/sh/boards/board-sh7757lcr.c
@@ -16,7 +16,7 @@
#include <linux/io.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/host.h>
-#include <linux/mmc/sh_mmcif.h>
+#include <linux/platform_data/sh_mmcif.h>
#include <linux/sh_eth.h>
#include <linux/sh_intc.h>
#include <linux/usb/renesas_usbhs.h>
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 4c9522dd351f..674da7ebd8b7 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -19,7 +19,7 @@
#include <linux/memblock.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/host.h>
-#include <linux/mmc/sh_mmcif.h>
+#include <linux/platform_data/sh_mmcif.h>
#include <linux/mtd/physmap.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
diff --git a/arch/sh/boot/romimage/mmcif-sh7724.c b/arch/sh/boot/romimage/mmcif-sh7724.c
index 6595b6b45bf1..d30123d859e0 100644
--- a/arch/sh/boot/romimage/mmcif-sh7724.c
+++ b/arch/sh/boot/romimage/mmcif-sh7724.c
@@ -8,7 +8,7 @@
* for more details.
*/
-#include <linux/mmc/sh_mmcif.h>
+#include <linux/platform_data/sh_mmcif.h>
#include <mach/romimage.h>
#define MMCIF_BASE (void __iomem *)0xa4ca0000
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 506dc900f5c7..1259ca22d625 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -126,6 +126,7 @@ struct mmc_blk_data {
#define MMC_BLK_DISCARD BIT(2)
#define MMC_BLK_SECDISCARD BIT(3)
#define MMC_BLK_CQE_RECOVERY BIT(4)
+#define MMC_BLK_TRIM BIT(5)
/*
* Only set in main mmc_blk_data associated
@@ -330,7 +331,7 @@ static struct attribute *mmc_disk_attrs[] = {
static umode_t mmc_disk_attrs_is_visible(struct kobject *kobj,
struct attribute *a, int n)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
umode_t mode = a->mode;
@@ -609,11 +610,11 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
if (idata->rpmb || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
/*
- * Ensure RPMB/R1B command has completed by polling CMD13
- * "Send Status".
+ * Ensure RPMB/R1B command has completed by polling CMD13 "Send Status". Here we
+ * allow to override the default timeout value if a custom timeout is specified.
*/
- err = mmc_poll_for_busy(card, MMC_BLK_TIMEOUT_MS, false,
- MMC_BUSY_IO);
+ err = mmc_poll_for_busy(card, idata->ic.cmd_timeout_ms ? : MMC_BLK_TIMEOUT_MS,
+ false, MMC_BUSY_IO);
}
return err;
@@ -676,8 +677,9 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
struct mmc_ioc_cmd __user *cmds = user->cmds;
struct mmc_card *card;
struct mmc_queue *mq;
- int i, err = 0, ioc_err = 0;
+ int err = 0, ioc_err = 0;
__u64 num_of_cmds;
+ unsigned int i, n;
struct request *req;
if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
@@ -690,15 +692,16 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
if (num_of_cmds > MMC_IOC_MAX_CMDS)
return -EINVAL;
- idata = kcalloc(num_of_cmds, sizeof(*idata), GFP_KERNEL);
+ n = num_of_cmds;
+ idata = kcalloc(n, sizeof(*idata), GFP_KERNEL);
if (!idata)
return -ENOMEM;
- for (i = 0; i < num_of_cmds; i++) {
+ for (i = 0; i < n; i++) {
idata[i] = mmc_blk_ioctl_copy_from_user(&cmds[i]);
if (IS_ERR(idata[i])) {
err = PTR_ERR(idata[i]);
- num_of_cmds = i;
+ n = i;
goto cmd_err;
}
/* This will be NULL on non-RPMB ioctl():s */
@@ -725,18 +728,18 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
req_to_mmc_queue_req(req)->drv_op =
rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
req_to_mmc_queue_req(req)->drv_op_data = idata;
- req_to_mmc_queue_req(req)->ioc_count = num_of_cmds;
+ req_to_mmc_queue_req(req)->ioc_count = n;
blk_execute_rq(req, false);
ioc_err = req_to_mmc_queue_req(req)->drv_op_result;
/* copy to user if data and response */
- for (i = 0; i < num_of_cmds && !err; i++)
+ for (i = 0; i < n && !err; i++)
err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
blk_mq_free_request(req);
cmd_err:
- for (i = 0; i < num_of_cmds; i++) {
+ for (i = 0; i < n; i++) {
kfree(idata[i]->buf);
kfree(idata[i]);
}
@@ -1090,12 +1093,13 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK);
}
-static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
+static void mmc_blk_issue_erase_rq(struct mmc_queue *mq, struct request *req,
+ int type, unsigned int erase_arg)
{
struct mmc_blk_data *md = mq->blkdata;
struct mmc_card *card = md->queue.card;
unsigned int from, nr;
- int err = 0, type = MMC_BLK_DISCARD;
+ int err = 0;
blk_status_t status = BLK_STS_OK;
if (!mmc_can_erase(card)) {
@@ -1111,13 +1115,13 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
INAND_CMD38_ARG_EXT_CSD,
- card->erase_arg == MMC_TRIM_ARG ?
+ erase_arg == MMC_TRIM_ARG ?
INAND_CMD38_ARG_TRIM :
INAND_CMD38_ARG_ERASE,
card->ext_csd.generic_cmd6_time);
}
if (!err)
- err = mmc_erase(card, from, nr, card->erase_arg);
+ err = mmc_erase(card, from, nr, erase_arg);
} while (err == -EIO && !mmc_blk_reset(md, card->host, type));
if (err)
status = BLK_STS_IOERR;
@@ -1127,6 +1131,19 @@ fail:
blk_mq_end_request(req, status);
}
+static void mmc_blk_issue_trim_rq(struct mmc_queue *mq, struct request *req)
+{
+ mmc_blk_issue_erase_rq(mq, req, MMC_BLK_TRIM, MMC_TRIM_ARG);
+}
+
+static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
+{
+ struct mmc_blk_data *md = mq->blkdata;
+ struct mmc_card *card = md->queue.card;
+
+ mmc_blk_issue_erase_rq(mq, req, MMC_BLK_DISCARD, card->erase_arg);
+}
+
static void mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
struct request *req)
{
@@ -2327,6 +2344,9 @@ enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue *mq, struct request *req)
case REQ_OP_SECURE_ERASE:
mmc_blk_issue_secdiscard_rq(mq, req);
break;
+ case REQ_OP_WRITE_ZEROES:
+ mmc_blk_issue_trim_rq(mq, req);
+ break;
case REQ_OP_FLUSH:
mmc_blk_issue_flush(mq, req);
break;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index c6ae16d40766..4b70cbfc6d5d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1988,9 +1988,9 @@ static void mmc_hw_reset_for_init(struct mmc_host *host)
{
mmc_pwrseq_reset(host);
- if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
+ if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->card_hw_reset)
return;
- host->ops->hw_reset(host);
+ host->ops->card_hw_reset(host);
}
/**
@@ -2017,8 +2017,9 @@ int mmc_hw_reset(struct mmc_card *card)
}
EXPORT_SYMBOL(mmc_hw_reset);
-int mmc_sw_reset(struct mmc_host *host)
+int mmc_sw_reset(struct mmc_card *card)
{
+ struct mmc_host *host = card->host;
int ret;
if (!host->bus_ops->sw_reset)
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index efa95dc4fc4e..89cd48fcec79 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/pm_runtime.h>
+#include <linux/random.h>
#include <linux/sysfs.h>
#include <linux/mmc/host.h>
@@ -72,6 +73,12 @@ static int mmc_decode_cid(struct mmc_card *card)
u32 *resp = card->raw_cid;
/*
+ * Add the raw card ID (cid) data to the entropy pool. It doesn't
+ * matter that not all of it is unique, it's just bonus entropy.
+ */
+ add_device_randomness(&card->raw_cid, sizeof(card->raw_cid));
+
+ /*
* The selection of the format here is based upon published
* specs from sandisk and from what people have reported.
*/
@@ -2240,11 +2247,11 @@ static int _mmc_hw_reset(struct mmc_host *host)
*/
_mmc_flush_cache(host);
- if ((host->caps & MMC_CAP_HW_RESET) && host->ops->hw_reset &&
+ if ((host->caps & MMC_CAP_HW_RESET) && host->ops->card_hw_reset &&
mmc_can_reset(card)) {
/* If the card accept RST_n signal, send it. */
mmc_set_clock(host, host->f_init);
- host->ops->hw_reset(host);
+ host->ops->card_hw_reset(host);
/* Set initial state and call mmc_set_ios */
mmc_set_initial_state(host);
} else {
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
index a3d446005571..fa5324ceeebe 100644
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -190,6 +190,8 @@ static void mmc_queue_setup_discard(struct request_queue *q,
q->limits.discard_granularity = SECTOR_SIZE;
if (mmc_can_secure_erase_trim(card))
blk_queue_max_secure_erase_sectors(q, max_discard);
+ if (mmc_can_trim(card) && card->erased_byte == 0)
+ blk_queue_max_write_zeroes_sectors(q, max_discard);
}
static unsigned short mmc_get_max_segments(struct mmc_host *host)
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 68df6b2f49cc..c5f1df6ce4c0 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/pm_runtime.h>
+#include <linux/random.h>
#include <linux/scatterlist.h>
#include <linux/sysfs.h>
@@ -84,6 +85,12 @@ void mmc_decode_cid(struct mmc_card *card)
u32 *resp = card->raw_cid;
/*
+ * Add the raw card ID (cid) data to the entropy pool. It doesn't
+ * matter that not all of it is unique, it's just bonus entropy.
+ */
+ add_device_randomness(&card->raw_cid, sizeof(card->raw_cid));
+
+ /*
* SD doesn't currently have a version field so we will
* have to assume we can parse this.
*/
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 807177c953f3..91d52ba7a39f 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -1122,13 +1122,12 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
}
/* If we don't have a channel, we can't do DMA */
- chan = host->dma.chan;
- if (chan)
- host->data_chan = chan;
-
- if (!chan)
+ if (!host->dma.chan)
return -ENODEV;
+ chan = host->dma.chan;
+ host->data_chan = chan;
+
if (data->flags & MMC_DATA_READ) {
host->dma_conf.direction = slave_dirn = DMA_DEV_TO_MEM;
maxburst = atmci_convert_chksize(host,
diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
index 463b707d9e99..641ab4f42125 100644
--- a/drivers/mmc/host/bcm2835.c
+++ b/drivers/mmc/host/bcm2835.c
@@ -1259,7 +1259,7 @@ static void bcm2835_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
static const struct mmc_host_ops bcm2835_ops = {
.request = bcm2835_request,
.set_ios = bcm2835_set_ios,
- .hw_reset = bcm2835_reset,
+ .card_hw_reset = bcm2835_reset,
};
static int bcm2835_add_host(struct bcm2835_host *host)
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 06dc56cbada8..581614196a84 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1812,7 +1812,7 @@ static const struct mmc_host_ops dw_mci_ops = {
.set_ios = dw_mci_set_ios,
.get_ro = dw_mci_get_ro,
.get_cd = dw_mci_get_cd,
- .hw_reset = dw_mci_hw_reset,
+ .card_hw_reset = dw_mci_hw_reset,
.enable_sdio_irq = dw_mci_enable_sdio_irq,
.ack_sdio_irq = dw_mci_ack_sdio_irq,
.execute_tuning = dw_mci_execute_tuning,
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index 7ab1b38a7be5..b1d563b2ed1b 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -247,6 +247,26 @@ static int jz4740_mmc_acquire_dma_channels(struct jz4740_mmc_host *host)
return PTR_ERR(host->dma_rx);
}
+ /*
+ * Limit the maximum segment size in any SG entry according to
+ * the parameters of the DMA engine device.
+ */
+ if (host->dma_tx) {
+ struct device *dev = host->dma_tx->device->dev;
+ unsigned int max_seg_size = dma_get_max_seg_size(dev);
+
+ if (max_seg_size < host->mmc->max_seg_size)
+ host->mmc->max_seg_size = max_seg_size;
+ }
+
+ if (host->dma_rx) {
+ struct device *dev = host->dma_rx->device->dev;
+ unsigned int max_seg_size = dma_get_max_seg_size(dev);
+
+ if (max_seg_size < host->mmc->max_seg_size)
+ host->mmc->max_seg_size = max_seg_size;
+ }
+
return 0;
}
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 58ab9d90bc8b..2f08d442e557 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -1271,8 +1271,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
/* data bounce buffer */
host->bounce_buf_size = mmc->max_req_size;
host->bounce_buf =
- dma_alloc_coherent(host->dev, host->bounce_buf_size,
- &host->bounce_dma_addr, GFP_KERNEL);
+ dmam_alloc_coherent(host->dev, host->bounce_buf_size,
+ &host->bounce_dma_addr, GFP_KERNEL);
if (host->bounce_buf == NULL) {
dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
ret = -ENOMEM;
@@ -1280,12 +1280,12 @@ static int meson_mmc_probe(struct platform_device *pdev)
}
}
- host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
- &host->descs_dma_addr, GFP_KERNEL);
+ host->descs = dmam_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
+ &host->descs_dma_addr, GFP_KERNEL);
if (!host->descs) {
dev_err(host->dev, "Allocating descriptor DMA buffer failed\n");
ret = -ENOMEM;
- goto err_bounce_buf;
+ goto err_free_irq;
}
mmc->ops = &meson_mmc_ops;
@@ -1293,10 +1293,6 @@ static int meson_mmc_probe(struct platform_device *pdev)
return 0;
-err_bounce_buf:
- if (!host->dram_access_quirk)
- dma_free_coherent(host->dev, host->bounce_buf_size,
- host->bounce_buf, host->bounce_dma_addr);
err_free_irq:
free_irq(host->irq, host);
err_init_clk:
@@ -1318,13 +1314,6 @@ static int meson_mmc_remove(struct platform_device *pdev)
writel(0, host->regs + SD_EMMC_IRQ_EN);
free_irq(host->irq, host);
- dma_free_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
- host->descs, host->descs_dma_addr);
-
- if (!host->dram_access_quirk)
- dma_free_coherent(host->dev, host->bounce_buf_size,
- host->bounce_buf, host->bounce_dma_addr);
-
clk_disable_unprepare(host->mmc_clk);
clk_disable_unprepare(host->core_clk);
diff --git a/drivers/mmc/host/meson-mx-sdhc-mmc.c b/drivers/mmc/host/meson-mx-sdhc-mmc.c
index 28aa78aa08f3..e92e63cb5641 100644
--- a/drivers/mmc/host/meson-mx-sdhc-mmc.c
+++ b/drivers/mmc/host/meson-mx-sdhc-mmc.c
@@ -511,7 +511,7 @@ static int meson_mx_sdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
}
static const struct mmc_host_ops meson_mx_sdhc_ops = {
- .hw_reset = meson_mx_sdhc_hw_reset,
+ .card_hw_reset = meson_mx_sdhc_hw_reset,
.request = meson_mx_sdhc_request,
.set_ios = meson_mx_sdhc_set_ios,
.card_busy = meson_mx_sdhc_card_busy,
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 45b8608c935c..01159eaf8694 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1619,6 +1619,8 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
do {
status = readl(host->base + MMCISTATUS);
+ if (!status)
+ break;
if (host->singleirq) {
if (status & host->mask1_reg)
@@ -1746,10 +1748,6 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
unsigned long flags;
int ret;
- if (host->plat->ios_handler &&
- host->plat->ios_handler(mmc_dev(mmc), ios))
- dev_err(mmc_dev(mmc), "platform ios_handler failed\n");
-
switch (ios->power_mode) {
case MMC_POWER_OFF:
if (!IS_ERR(mmc->supply.vmmc))
diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c
index 4566d7fc9055..60bca78a72b1 100644
--- a/drivers/mmc/host/mmci_stm32_sdmmc.c
+++ b/drivers/mmc/host/mmci_stm32_sdmmc.c
@@ -43,6 +43,9 @@ struct sdmmc_lli_desc {
struct sdmmc_idma {
dma_addr_t sg_dma;
void *sg_cpu;
+ dma_addr_t bounce_dma_addr;
+ void *bounce_buf;
+ bool use_bounce_buffer;
};
struct sdmmc_dlyb {
@@ -54,6 +57,8 @@ struct sdmmc_dlyb {
static int sdmmc_idma_validate_data(struct mmci_host *host,
struct mmc_data *data)
{
+ struct sdmmc_idma *idma = host->dma_priv;
+ struct device *dev = mmc_dev(host->mmc);
struct scatterlist *sg;
int i;
@@ -61,41 +66,69 @@ static int sdmmc_idma_validate_data(struct mmci_host *host,
* idma has constraints on idmabase & idmasize for each element
* excepted the last element which has no constraint on idmasize
*/
+ idma->use_bounce_buffer = false;
for_each_sg(data->sg, sg, data->sg_len - 1, i) {
if (!IS_ALIGNED(sg->offset, sizeof(u32)) ||
!IS_ALIGNED(sg->length, SDMMC_IDMA_BURST)) {
- dev_err(mmc_dev(host->mmc),
+ dev_dbg(mmc_dev(host->mmc),
"unaligned scatterlist: ofst:%x length:%d\n",
data->sg->offset, data->sg->length);
- return -EINVAL;
+ goto use_bounce_buffer;
}
}
if (!IS_ALIGNED(sg->offset, sizeof(u32))) {
- dev_err(mmc_dev(host->mmc),
+ dev_dbg(mmc_dev(host->mmc),
"unaligned last scatterlist: ofst:%x length:%d\n",
data->sg->offset, data->sg->length);
- return -EINVAL;
+ goto use_bounce_buffer;
}
return 0;
+
+use_bounce_buffer:
+ if (!idma->bounce_buf) {
+ idma->bounce_buf = dmam_alloc_coherent(dev,
+ host->mmc->max_req_size,
+ &idma->bounce_dma_addr,
+ GFP_KERNEL);
+ if (!idma->bounce_buf) {
+ dev_err(dev, "Unable to map allocate DMA bounce buffer.\n");
+ return -ENOMEM;
+ }
+ }
+
+ idma->use_bounce_buffer = true;
+
+ return 0;
}
static int _sdmmc_idma_prep_data(struct mmci_host *host,
struct mmc_data *data)
{
- int n_elem;
+ struct sdmmc_idma *idma = host->dma_priv;
- n_elem = dma_map_sg(mmc_dev(host->mmc),
- data->sg,
- data->sg_len,
- mmc_get_dma_dir(data));
+ if (idma->use_bounce_buffer) {
+ if (data->flags & MMC_DATA_WRITE) {
+ unsigned int xfer_bytes = data->blksz * data->blocks;
- if (!n_elem) {
- dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n");
- return -EINVAL;
- }
+ sg_copy_to_buffer(data->sg, data->sg_len,
+ idma->bounce_buf, xfer_bytes);
+ dma_wmb();
+ }
+ } else {
+ int n_elem;
+
+ n_elem = dma_map_sg(mmc_dev(host->mmc),
+ data->sg,
+ data->sg_len,
+ mmc_get_dma_dir(data));
+ if (!n_elem) {
+ dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n");
+ return -EINVAL;
+ }
+ }
return 0;
}
@@ -112,8 +145,19 @@ static int sdmmc_idma_prep_data(struct mmci_host *host,
static void sdmmc_idma_unprep_data(struct mmci_host *host,
struct mmc_data *data, int err)
{
- dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- mmc_get_dma_dir(data));
+ struct sdmmc_idma *idma = host->dma_priv;
+
+ if (idma->use_bounce_buffer) {
+ if (data->flags & MMC_DATA_READ) {
+ unsigned int xfer_bytes = data->blksz * data->blocks;
+
+ sg_copy_from_buffer(data->sg, data->sg_len,
+ idma->bounce_buf, xfer_bytes);
+ }
+ } else {
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+ mmc_get_dma_dir(data));
+ }
}
static int sdmmc_idma_setup(struct mmci_host *host)
@@ -137,6 +181,8 @@ static int sdmmc_idma_setup(struct mmci_host *host)
host->mmc->max_segs = SDMMC_LLI_BUF_LEN /
sizeof(struct sdmmc_lli_desc);
host->mmc->max_seg_size = host->variant->stm32_idmabsize_mask;
+
+ host->mmc->max_req_size = SZ_1M;
} else {
host->mmc->max_segs = 1;
host->mmc->max_seg_size = host->mmc->max_req_size;
@@ -154,8 +200,16 @@ static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl)
struct scatterlist *sg;
int i;
- if (!host->variant->dma_lli || data->sg_len == 1) {
- writel_relaxed(sg_dma_address(data->sg),
+ if (!host->variant->dma_lli || data->sg_len == 1 ||
+ idma->use_bounce_buffer) {
+ u32 dma_addr;
+
+ if (idma->use_bounce_buffer)
+ dma_addr = idma->bounce_dma_addr;
+ else
+ dma_addr = sg_dma_address(data->sg);
+
+ writel_relaxed(dma_addr,
host->base + MMCI_STM32_IDMABASE0R);
writel_relaxed(MMCI_STM32_IDMAEN,
host->base + MMCI_STM32_IDMACTRLR);
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index e61b0b98065a..195dc897188b 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -2458,7 +2458,7 @@ static const struct mmc_host_ops mt_msdc_ops = {
.execute_tuning = msdc_execute_tuning,
.prepare_hs400_tuning = msdc_prepare_hs400_tuning,
.execute_hs400_tuning = msdc_execute_hs400_tuning,
- .hw_reset = msdc_hw_reset,
+ .card_hw_reset = msdc_hw_reset,
};
static const struct cqhci_host_ops msdc_cmdq_ops = {
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
index 3629550528b6..bf54776fb26c 100644
--- a/drivers/mmc/host/of_mmc_spi.c
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -70,6 +70,10 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
} else {
oms->pdata.caps |= MMC_CAP_NEEDS_POLL;
}
+ if (device_property_read_bool(dev, "cap-sd-highspeed"))
+ oms->pdata.caps |= MMC_CAP_SD_HIGHSPEED;
+ if (device_property_read_bool(dev, "cap-mmc-highspeed"))
+ oms->pdata.caps |= MMC_CAP_MMC_HIGHSPEED;
dev->platform_data = &oms->pdata;
return dev->platform_data;
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 5e5af34090f1..57d39283924d 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1374,7 +1374,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
host->iclk = clk_get(&pdev->dev, "ick");
if (IS_ERR(host->iclk))
return PTR_ERR(host->iclk);
- clk_enable(host->iclk);
+ clk_prepare_enable(host->iclk);
host->fclk = clk_get(&pdev->dev, "fck");
if (IS_ERR(host->fclk)) {
@@ -1382,16 +1382,18 @@ static int mmc_omap_probe(struct platform_device *pdev)
goto err_free_iclk;
}
+ ret = clk_prepare(host->fclk);
+ if (ret)
+ goto err_put_fclk;
+
host->dma_tx_burst = -1;
host->dma_rx_burst = -1;
host->dma_tx = dma_request_chan(&pdev->dev, "tx");
if (IS_ERR(host->dma_tx)) {
ret = PTR_ERR(host->dma_tx);
- if (ret == -EPROBE_DEFER) {
- clk_put(host->fclk);
- goto err_free_iclk;
- }
+ if (ret == -EPROBE_DEFER)
+ goto err_free_fclk;
host->dma_tx = NULL;
dev_warn(host->dev, "TX DMA channel request failed\n");
@@ -1403,8 +1405,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
if (ret == -EPROBE_DEFER) {
if (host->dma_tx)
dma_release_channel(host->dma_tx);
- clk_put(host->fclk);
- goto err_free_iclk;
+ goto err_free_fclk;
}
host->dma_rx = NULL;
@@ -1454,9 +1455,12 @@ err_free_dma:
dma_release_channel(host->dma_tx);
if (host->dma_rx)
dma_release_channel(host->dma_rx);
+err_free_fclk:
+ clk_unprepare(host->fclk);
+err_put_fclk:
clk_put(host->fclk);
err_free_iclk:
- clk_disable(host->iclk);
+ clk_disable_unprepare(host->iclk);
clk_put(host->iclk);
return ret;
}
@@ -1476,8 +1480,9 @@ static int mmc_omap_remove(struct platform_device *pdev)
mmc_omap_fclk_enable(host, 0);
free_irq(host->irq, host);
+ clk_unprepare(host->fclk);
clk_put(host->fclk);
- clk_disable(host->iclk);
+ clk_disable_unprepare(host->iclk);
clk_put(host->iclk);
if (host->dma_tx)
diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h
index 66d308e73e17..1a1e3e020a8c 100644
--- a/drivers/mmc/host/renesas_sdhi.h
+++ b/drivers/mmc/host/renesas_sdhi.h
@@ -41,6 +41,8 @@ struct renesas_sdhi_of_data {
struct renesas_sdhi_quirks {
bool hs400_disabled;
bool hs400_4taps;
+ bool fixed_addr_mode;
+ bool dma_one_rx_only;
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 ddb5ca2f559e..4404ca1f98d8 100644
--- a/drivers/mmc/host/renesas_sdhi_core.c
+++ b/drivers/mmc/host/renesas_sdhi_core.c
@@ -27,7 +27,6 @@
#include <linux/mmc/mmc.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/module.h>
-#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl-state.h>
#include <linux/platform_device.h>
@@ -36,7 +35,6 @@
#include <linux/reset.h>
#include <linux/sh_dma.h>
#include <linux/slab.h>
-#include <linux/sys_soc.h>
#include "renesas_sdhi.h"
#include "tmio_mmc.h"
diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
index 1685df00863b..3084b15ae2cb 100644
--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -78,11 +78,7 @@ static unsigned long global_flags;
* stored into the system memory even if the DMAC interrupt happened.
* So, this driver then uses one RX DMAC channel only.
*/
-#define SDHI_INTERNAL_DMAC_ONE_RX_ONLY 0
-#define SDHI_INTERNAL_DMAC_RX_IN_USE 1
-
-/* RZ/A2 does not have the ADRR_MODE bit */
-#define SDHI_INTERNAL_DMAC_ADDR_MODE_FIXED_ONLY 2
+#define SDHI_INTERNAL_DMAC_RX_IN_USE 0
/* Definitions for sampling clocks */
static struct renesas_sdhi_scc rcar_gen3_scc_taps[] = {
@@ -108,10 +104,6 @@ static const struct renesas_sdhi_of_data of_data_rza2 = {
.max_segs = 1,
};
-static const struct renesas_sdhi_of_data_with_quirks of_rza2_compatible = {
- .of_data = &of_data_rza2,
-};
-
static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |
TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2,
@@ -128,7 +120,7 @@ static const struct renesas_sdhi_of_data of_data_rcar_gen3 = {
.sdhi_flags = SDHI_FLAG_NEED_CLKH_FALLBACK,
};
-static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_fallback = {
+static const struct renesas_sdhi_of_data of_data_rcar_gen3_no_sdh_fallback = {
.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL |
TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2,
.capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
@@ -169,6 +161,12 @@ static const struct renesas_sdhi_quirks sdhi_quirks_4tap_nohs400 = {
.hs400_4taps = true,
};
+static const struct renesas_sdhi_quirks sdhi_quirks_4tap_nohs400_one_rx = {
+ .hs400_disabled = true,
+ .hs400_4taps = true,
+ .dma_one_rx_only = true,
+};
+
static const struct renesas_sdhi_quirks sdhi_quirks_4tap = {
.hs400_4taps = true,
.hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7),
@@ -178,6 +176,10 @@ static const struct renesas_sdhi_quirks sdhi_quirks_nohs400 = {
.hs400_disabled = true,
};
+static const struct renesas_sdhi_quirks sdhi_quirks_fixed_addr = {
+ .fixed_addr_mode = true,
+};
+
static const struct renesas_sdhi_quirks sdhi_quirks_bad_taps1357 = {
.hs400_bad_taps = BIT(1) | BIT(3) | BIT(5) | BIT(7),
};
@@ -208,10 +210,12 @@ static const struct renesas_sdhi_quirks sdhi_quirks_r8a77990 = {
*/
static const struct soc_device_attribute sdhi_quirks_match[] = {
{ .soc_id = "r8a774a1", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 },
- { .soc_id = "r8a7795", .revision = "ES1.*", .data = &sdhi_quirks_4tap_nohs400 },
+ { .soc_id = "r8a7795", .revision = "ES1.*", .data = &sdhi_quirks_4tap_nohs400_one_rx },
{ .soc_id = "r8a7795", .revision = "ES2.0", .data = &sdhi_quirks_4tap },
- { .soc_id = "r8a7796", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 },
+ { .soc_id = "r8a7796", .revision = "ES1.0", .data = &sdhi_quirks_4tap_nohs400_one_rx },
+ { .soc_id = "r8a7796", .revision = "ES1.[12]", .data = &sdhi_quirks_4tap_nohs400 },
{ .soc_id = "r8a7796", .revision = "ES1.*", .data = &sdhi_quirks_r8a7796_es13 },
+ { .soc_id = "r8a77980", .revision = "ES1.*", .data = &sdhi_quirks_nohs400 },
{ /* Sentinel. */ }
};
@@ -231,11 +235,7 @@ static const struct renesas_sdhi_of_data_with_quirks of_r8a77965_compatible = {
};
static const struct renesas_sdhi_of_data_with_quirks of_r8a77970_compatible = {
- .of_data = &of_data_rcar_gen3_no_fallback,
-};
-
-static const struct renesas_sdhi_of_data_with_quirks of_r8a77980_compatible = {
- .of_data = &of_data_rcar_gen3,
+ .of_data = &of_data_rcar_gen3_no_sdh_fallback,
.quirks = &sdhi_quirks_nohs400,
};
@@ -248,16 +248,25 @@ static const struct renesas_sdhi_of_data_with_quirks of_rcar_gen3_compatible = {
.of_data = &of_data_rcar_gen3,
};
+static const struct renesas_sdhi_of_data_with_quirks of_rcar_gen3_nohs400_compatible = {
+ .of_data = &of_data_rcar_gen3,
+ .quirks = &sdhi_quirks_nohs400,
+};
+
+static const struct renesas_sdhi_of_data_with_quirks of_rza2_compatible = {
+ .of_data = &of_data_rza2,
+ .quirks = &sdhi_quirks_fixed_addr,
+};
+
static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = {
{ .compatible = "renesas,sdhi-r7s9210", .data = &of_rza2_compatible, },
{ .compatible = "renesas,sdhi-mmc-r8a77470", .data = &of_rcar_gen3_compatible, },
{ .compatible = "renesas,sdhi-r8a7795", .data = &of_r8a7795_compatible, },
- { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, },
{ .compatible = "renesas,sdhi-r8a77961", .data = &of_r8a77961_compatible, },
{ .compatible = "renesas,sdhi-r8a77965", .data = &of_r8a77965_compatible, },
{ .compatible = "renesas,sdhi-r8a77970", .data = &of_r8a77970_compatible, },
- { .compatible = "renesas,sdhi-r8a77980", .data = &of_r8a77980_compatible, },
{ .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, },
{},
};
@@ -287,7 +296,8 @@ renesas_sdhi_internal_dmac_enable_dma(struct tmio_mmc_host *host, bool enable)
}
static void
-renesas_sdhi_internal_dmac_abort_dma(struct tmio_mmc_host *host) {
+renesas_sdhi_internal_dmac_abort_dma(struct tmio_mmc_host *host)
+{
u64 val = RST_DTRANRST1 | RST_DTRANRST0;
renesas_sdhi_internal_dmac_enable_dma(host, false);
@@ -303,7 +313,8 @@ renesas_sdhi_internal_dmac_abort_dma(struct tmio_mmc_host *host) {
}
static void
-renesas_sdhi_internal_dmac_dataend_dma(struct tmio_mmc_host *host) {
+renesas_sdhi_internal_dmac_dataend_dma(struct tmio_mmc_host *host)
+{
struct renesas_sdhi *priv = host_to_priv(host);
tasklet_schedule(&priv->dma_priv.dma_complete);
@@ -357,10 +368,11 @@ static void
renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host,
struct mmc_data *data)
{
+ struct renesas_sdhi *priv = host_to_priv(host);
struct scatterlist *sg = host->sg_ptr;
u32 dtran_mode = DTRAN_MODE_BUS_WIDTH;
- if (!test_bit(SDHI_INTERNAL_DMAC_ADDR_MODE_FIXED_ONLY, &global_flags))
+ if (!(priv->quirks && priv->quirks->fixed_addr_mode))
dtran_mode |= DTRAN_MODE_ADDR_MODE;
if (!renesas_sdhi_internal_dmac_map(host, data, COOKIE_MAPPED))
@@ -368,7 +380,7 @@ renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host,
if (data->flags & MMC_DATA_READ) {
dtran_mode |= DTRAN_MODE_CH_NUM_CH1;
- if (test_bit(SDHI_INTERNAL_DMAC_ONE_RX_ONLY, &global_flags) &&
+ if (priv->quirks && priv->quirks->dma_one_rx_only &&
test_and_set_bit(SDHI_INTERNAL_DMAC_RX_IN_USE, &global_flags))
goto force_pio_with_unmap;
} else {
@@ -520,20 +532,6 @@ static const struct tmio_mmc_dma_ops renesas_sdhi_internal_dmac_dma_ops = {
.end = renesas_sdhi_internal_dmac_end_dma,
};
-/*
- * Whitelist of specific R-Car Gen3 SoC ES versions to use this DMAC
- * implementation as others may use a different implementation.
- */
-static const struct soc_device_attribute soc_dma_quirks[] = {
- { .soc_id = "r7s9210",
- .data = (void *)BIT(SDHI_INTERNAL_DMAC_ADDR_MODE_FIXED_ONLY) },
- { .soc_id = "r8a7795", .revision = "ES1.*",
- .data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) },
- { .soc_id = "r8a7796", .revision = "ES1.0",
- .data = (void *)BIT(SDHI_INTERNAL_DMAC_ONE_RX_ONLY) },
- { /* sentinel */ }
-};
-
static int renesas_sdhi_internal_dmac_probe(struct platform_device *pdev)
{
const struct soc_device_attribute *attr;
@@ -544,10 +542,6 @@ static int renesas_sdhi_internal_dmac_probe(struct platform_device *pdev)
of_data_quirks = of_device_get_match_data(&pdev->dev);
quirks = of_data_quirks->quirks;
- attr = soc_device_match(soc_dma_quirks);
- if (attr)
- global_flags |= (unsigned long)attr->data;
-
attr = soc_device_match(sdhi_quirks_match);
if (attr)
quirks = attr->data;
diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c
index f24623aac2db..8eb57de48e0c 100644
--- a/drivers/mmc/host/sdhci-brcmstb.c
+++ b/drivers/mmc/host/sdhci-brcmstb.c
@@ -17,23 +17,49 @@
#define SDHCI_VENDOR 0x78
#define SDHCI_VENDOR_ENHANCED_STRB 0x1
+#define SDHCI_VENDOR_GATE_SDCLK_EN 0x2
-#define BRCMSTB_PRIV_FLAGS_NO_64BIT BIT(0)
-#define BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT BIT(1)
+#define BRCMSTB_MATCH_FLAGS_NO_64BIT BIT(0)
+#define BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT BIT(1)
+#define BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE BIT(2)
+
+#define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0)
+#define BRCMSTB_PRIV_FLAGS_GATE_CLOCK BIT(1)
#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
struct sdhci_brcmstb_priv {
void __iomem *cfg_regs;
- bool has_cqe;
+ unsigned int flags;
};
struct brcmstb_match_priv {
void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
struct sdhci_ops *ops;
- unsigned int flags;
+ const unsigned int flags;
};
+static inline void enable_clock_gating(struct sdhci_host *host)
+{
+ u32 reg;
+
+ reg = sdhci_readl(host, SDHCI_VENDOR);
+ reg |= SDHCI_VENDOR_GATE_SDCLK_EN;
+ sdhci_writel(host, reg, SDHCI_VENDOR);
+}
+
+static void brcmstb_reset(struct sdhci_host *host, u8 mask)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
+
+ sdhci_reset(host, mask);
+
+ /* Reset will clear this, so re-enable it */
+ if (priv->flags & BRCMSTB_PRIV_FLAGS_GATE_CLOCK)
+ enable_clock_gating(host);
+}
+
static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct sdhci_host *host = mmc_priv(mmc);
@@ -129,22 +155,23 @@ static struct sdhci_ops sdhci_brcmstb_ops = {
static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
.set_clock = sdhci_brcmstb_set_clock,
.set_bus_width = sdhci_set_bus_width,
- .reset = sdhci_reset,
+ .reset = brcmstb_reset,
.set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling,
};
static struct brcmstb_match_priv match_priv_7425 = {
- .flags = BRCMSTB_PRIV_FLAGS_NO_64BIT |
- BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT,
+ .flags = BRCMSTB_MATCH_FLAGS_NO_64BIT |
+ BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT,
.ops = &sdhci_brcmstb_ops,
};
static struct brcmstb_match_priv match_priv_7445 = {
- .flags = BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT,
+ .flags = BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT,
.ops = &sdhci_brcmstb_ops,
};
static const struct brcmstb_match_priv match_priv_7216 = {
+ .flags = BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE,
.hs400es = sdhci_brcmstb_hs400es,
.ops = &sdhci_brcmstb_ops_7216,
};
@@ -176,7 +203,7 @@ static int sdhci_brcmstb_add_host(struct sdhci_host *host,
bool dma64;
int ret;
- if (!priv->has_cqe)
+ if ((priv->flags & BRCMSTB_PRIV_FLAGS_HAS_CQE) == 0)
return sdhci_add_host(host);
dev_dbg(mmc_dev(host->mmc), "CQE is enabled\n");
@@ -225,7 +252,6 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
struct sdhci_brcmstb_priv *priv;
struct sdhci_host *host;
struct resource *iomem;
- bool has_cqe = false;
struct clk *clk;
int res;
@@ -244,10 +270,6 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
return res;
memset(&brcmstb_pdata, 0, sizeof(brcmstb_pdata));
- if (device_property_read_bool(&pdev->dev, "supports-cqe")) {
- has_cqe = true;
- match_priv->ops->irq = sdhci_brcmstb_cqhci_irq;
- }
brcmstb_pdata.ops = match_priv->ops;
host = sdhci_pltfm_init(pdev, &brcmstb_pdata,
sizeof(struct sdhci_brcmstb_priv));
@@ -258,7 +280,10 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host);
- priv->has_cqe = has_cqe;
+ if (device_property_read_bool(&pdev->dev, "supports-cqe")) {
+ priv->flags |= BRCMSTB_PRIV_FLAGS_HAS_CQE;
+ match_priv->ops->irq = sdhci_brcmstb_cqhci_irq;
+ }
/* Map in the non-standard CFG registers */
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -274,6 +299,14 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
goto err;
/*
+ * Automatic clock gating does not work for SD cards that may
+ * voltage switch so only enable it for non-removable devices.
+ */
+ if ((match_priv->flags & BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE) &&
+ (host->mmc->caps & MMC_CAP_NONREMOVABLE))
+ priv->flags |= BRCMSTB_PRIV_FLAGS_GATE_CLOCK;
+
+ /*
* If the chip has enhanced strobe and it's enabled, add
* callback
*/
@@ -287,14 +320,14 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
* properties through mmc_of_parse().
*/
host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
- if (match_priv->flags & BRCMSTB_PRIV_FLAGS_NO_64BIT)
+ if (match_priv->flags & BRCMSTB_MATCH_FLAGS_NO_64BIT)
host->caps &= ~SDHCI_CAN_64BIT;
host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
SDHCI_SUPPORT_DDR50);
host->quirks |= SDHCI_QUIRK_MISSING_CAPS;
- if (match_priv->flags & BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT)
+ if (match_priv->flags & BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT)
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
res = sdhci_brcmstb_add_host(host, priv);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index ff9f5b63c337..e395411fb6fd 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2435,8 +2435,33 @@ 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) */
{.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},
{},
diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
index 6a2e5a468424..757801dfc308 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -1577,6 +1577,9 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
const struct sdhci_arasan_of_data *data;
data = of_device_get_match_data(dev);
+ if (!data)
+ return -EINVAL;
+
host = sdhci_pltfm_init(pdev, data->pdata, sizeof(*sdhci_arasan));
if (IS_ERR(host))
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
index 64e27c2821f9..86e867ffbb10 100644
--- a/drivers/mmc/host/sdhci-omap.c
+++ b/drivers/mmc/host/sdhci-omap.c
@@ -1219,16 +1219,11 @@ static int sdhci_omap_probe(struct platform_device *pdev)
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_omap_host *omap_host;
struct mmc_host *mmc;
- const struct of_device_id *match;
- struct sdhci_omap_data *data;
+ const struct sdhci_omap_data *data;
const struct soc_device_attribute *soc;
struct resource *regs;
- match = of_match_device(omap_sdhci_match, dev);
- if (!match)
- return -EINVAL;
-
- data = (struct sdhci_omap_data *)match->data;
+ data = of_device_get_match_data(&pdev->dev);
if (!data) {
dev_err(dev, "no sdhci omap data\n");
return -EINVAL;
diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
index d09728c37d03..1499a64ec3aa 100644
--- a/drivers/mmc/host/sdhci-pci-gli.c
+++ b/drivers/mmc/host/sdhci-pci-gli.c
@@ -142,6 +142,9 @@
#define PCI_GLI_9755_MISC 0x78
#define PCI_GLI_9755_MISC_SSC_OFF BIT(26)
+#define PCI_GLI_9755_PM_CTRL 0xFC
+#define PCI_GLI_9755_PM_STATE GENMASK(1, 0)
+
#define GLI_MAX_TUNING_LOOP 40
/* Genesys Logic chipset */
@@ -676,6 +679,13 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot)
GLI_9755_CFG2_L1DLY_VALUE);
pci_write_config_dword(pdev, PCI_GLI_9755_CFG2, value);
+ /* toggle PM state to allow GL9755 to enter ASPM L1.2 */
+ pci_read_config_dword(pdev, PCI_GLI_9755_PM_CTRL, &value);
+ value |= PCI_GLI_9755_PM_STATE;
+ pci_write_config_dword(pdev, PCI_GLI_9755_PM_CTRL, value);
+ value &= ~PCI_GLI_9755_PM_STATE;
+ pci_write_config_dword(pdev, PCI_GLI_9755_PM_CTRL, value);
+
gl9755_wt_off(pdev);
}
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 07c6da1f2f0f..22152029e14c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2999,7 +2999,7 @@ static const struct mmc_host_ops sdhci_ops = {
.set_ios = sdhci_set_ios,
.get_cd = sdhci_get_cd,
.get_ro = sdhci_get_ro,
- .hw_reset = sdhci_hw_reset,
+ .card_hw_reset = sdhci_hw_reset,
.enable_sdio_irq = sdhci_enable_sdio_irq,
.ack_sdio_irq = sdhci_ack_sdio_irq,
.start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
index e54fe24d47e7..e7ced1496a07 100644
--- a/drivers/mmc/host/sdhci_am654.c
+++ b/drivers/mmc/host/sdhci_am654.c
@@ -147,6 +147,9 @@ struct sdhci_am654_data {
int drv_strength;
int strb_sel;
u32 flags;
+ u32 quirks;
+
+#define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0)
};
struct sdhci_am654_driver_data {
@@ -369,6 +372,21 @@ static void sdhci_am654_write_b(struct sdhci_host *host, u8 val, int reg)
}
}
+static void sdhci_am654_reset(struct sdhci_host *host, u8 mask)
+{
+ u8 ctrl;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);
+
+ sdhci_reset(host, mask);
+
+ if (sdhci_am654->quirks & SDHCI_AM654_QUIRK_FORCE_CDTEST) {
+ ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+ ctrl |= SDHCI_CTRL_CDTEST_INS | SDHCI_CTRL_CDTEST_EN;
+ sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+ }
+}
+
static int sdhci_am654_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct sdhci_host *host = mmc_priv(mmc);
@@ -500,7 +518,7 @@ static struct sdhci_ops sdhci_j721e_4bit_ops = {
.set_clock = sdhci_j721e_4bit_set_clock,
.write_b = sdhci_am654_write_b,
.irq = sdhci_am654_cqhci_irq,
- .reset = sdhci_reset,
+ .reset = sdhci_am654_reset,
};
static const struct sdhci_pltfm_data sdhci_j721e_4bit_pdata = {
@@ -719,6 +737,9 @@ static int sdhci_am654_get_of_property(struct platform_device *pdev,
device_property_read_u32(dev, "ti,clkbuf-sel",
&sdhci_am654->clkbuf_sel);
+ if (device_property_read_bool(dev, "ti,fails-without-test-cd"))
+ sdhci_am654->quirks |= SDHCI_AM654_QUIRK_FORCE_CDTEST;
+
sdhci_get_of_property(pdev);
return 0;
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 5f9ebf045b1c..0fd4c9d644dd 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -43,12 +43,12 @@
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sdio.h>
-#include <linux/mmc/sh_mmcif.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/pagemap.h>
+#include <linux/platform_data/sh_mmcif.h>
#include <linux/platform_device.h>
#include <linux/pm_qos.h>
#include <linux/pm_runtime.h>
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 46f9e2923d86..b16e12e62e72 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -1116,7 +1116,7 @@ static const struct mmc_host_ops sunxi_mmc_ops = {
.get_cd = mmc_gpio_get_cd,
.enable_sdio_irq = sunxi_mmc_enable_sdio_irq,
.start_signal_voltage_switch = sunxi_mmc_volt_switch,
- .hw_reset = sunxi_mmc_hw_reset,
+ .card_hw_reset = sunxi_mmc_hw_reset,
.card_busy = sunxi_mmc_card_busy,
};
diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c
index ccbf9885a52b..3a8defdcca77 100644
--- a/drivers/mmc/host/uniphier-sd.c
+++ b/drivers/mmc/host/uniphier-sd.c
@@ -597,7 +597,7 @@ static int uniphier_sd_probe(struct platform_device *pdev)
ret = PTR_ERR(priv->rst_hw);
goto free_host;
}
- host->ops.hw_reset = uniphier_sd_hw_reset;
+ host->ops.card_hw_reset = uniphier_sd_hw_reset;
}
if (host->mmc->caps & MMC_CAP_UHS) {
diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h
index c92ebc39fc1f..6f96dc2209c0 100644
--- a/include/linux/amba/mmci.h
+++ b/include/linux/amba/mmci.h
@@ -13,17 +13,11 @@
* @ocr_mask: available voltages on the 4 pins from the block, this
* is ignored if a regulator is used, see the MMC_VDD_* masks in
* mmc/host.h
- * @ios_handler: a callback function to act on specfic ios changes,
- * used for example to control a levelshifter
- * mask into a value to be binary (or set some other custom bits
- * in MMCIPWR) or:ed and written into the MMCIPWR register of the
- * block. May also control external power based on the power_mode.
* @status: if no GPIO line was given to the block in this function will
* be called to determine whether a card is present in the MMC slot or not
*/
struct mmci_platform_data {
unsigned int ocr_mask;
- int (*ios_handler)(struct device *, struct mmc_ios *);
unsigned int (*status)(struct device *);
};
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index de5c64bbdb72..6efec0b9820c 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -176,7 +176,7 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd,
int retries);
int mmc_hw_reset(struct mmc_card *card);
-int mmc_sw_reset(struct mmc_host *host);
+int mmc_sw_reset(struct mmc_card *card);
void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card);
#endif /* LINUX_MMC_CORE_H */
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 7afb57cab00b..c193c50ccd78 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -181,7 +181,7 @@ struct mmc_host_ops {
unsigned int max_dtr, int host_drv,
int card_drv, int *drv_type);
/* Reset the eMMC card via RST_n */
- void (*hw_reset)(struct mmc_host *host);
+ void (*card_hw_reset)(struct mmc_host *host);
void (*card_event)(struct mmc_host *host);
/*
diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/platform_data/sh_mmcif.h
index e25533b95d9f..6eb914f958f9 100644
--- a/include/linux/mmc/sh_mmcif.h
+++ b/include/linux/platform_data/sh_mmcif.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * include/linux/mmc/sh_mmcif.h
- *
* platform data for eMMC driver
*
* Copyright (C) 2010 Renesas Solutions Corp.