diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-09 11:39:39 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-09 11:39:39 -0400 |
| commit | 97e18dc007546fce8e99098480b921a02ebb3037 (patch) | |
| tree | f38c022d034e0172e83f6972983577f790f24dac | |
| parent | 042f7b7cbd1e531278a09c449563165ba1f07673 (diff) | |
| parent | c67480173f72e883235dd0ad09d90156c8f87600 (diff) | |
Merge tag 'mmc-updates-for-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
Pull MMC updates from Chris Ball:
"MMC highlights for 3.15:
Core:
- CONFIG_MMC_UNSAFE_RESUME=y is now default behavior
- DT bindings for SDHCI UHS, eMMC HS200, high-speed DDR, at 1.8/1.2V
- Add GPIO descriptor based slot-gpio card detect API
Drivers:
- dw_mmc: Refactor SOCFPGA support as a variant inside dw_mmc-pltfm.c
- mmci: Support HW busy detection on ux500
- omap: Support MMC_ERASE
- omap_hsmmc: Support MMC_PM_KEEP_POWER, MMC_PM_WAKE_SDIO_IRQ, (a)cmd23
- rtsx: Support pre-req/post-req async
- sdhci: Add support for Realtek RTS5250 controllers
- sdhci-acpi: Add support for 80860F16, fix 80860F14/SDIO card detect
- sdhci-msm: Add new driver for Qualcomm SDHCI chipset support
- sdhci-pxav3: Add support for Marvell Armada 380 and 385 SoCs"
* tag 'mmc-updates-for-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (102 commits)
mmc: sdhci-acpi: Intel SDIO has broken card detect
mmc: sdhci-pxav3: add support for the Armada 38x SDHCI controller
mmc: sdhci-msm: Add platform_execute_tuning implementation
mmc: sdhci-msm: Initial support for Qualcomm chipsets
mmc: sdhci-msm: Qualcomm SDHCI binding documentation
sdhci: only reprogram retuning timer when flag is set
mmc: rename ARCH_BCM to ARCH_BCM_MOBILE
mmc: sdhci: Allow for irq being shared
mmc: sdhci-acpi: Add device id 80860F16
mmc: sdhci-acpi: Fix broken card detect for ACPI HID 80860F14
mmc: slot-gpio: Add GPIO descriptor based CD GPIO API
mmc: slot-gpio: Split out CD IRQ request into a separate function
mmc: slot-gpio: Record GPIO descriptors instead of GPIO numbers
Revert "dts: socfpga: Add support for SD/MMC on the SOCFPGA platform"
mmc: sdhci-spear: use generic card detection gpio support
mmc: sdhci-spear: remove support for power gpio
mmc: sdhci-spear: simplify resource handling
mmc: sdhci-spear: fix platform_data usage
mmc: sdhci-spear: fix error handling paths for DT
mmc: sdhci-bcm-kona: fix build errors when built-in
...
63 files changed, 2577 insertions, 1166 deletions
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt index 458b57f199af..9dce540771fb 100644 --- a/Documentation/devicetree/bindings/mmc/mmc.txt +++ b/Documentation/devicetree/bindings/mmc/mmc.txt | |||
| @@ -26,9 +26,18 @@ Optional properties: | |||
| 26 | this system, even if the controller claims it is. | 26 | this system, even if the controller claims it is. |
| 27 | - cap-sd-highspeed: SD high-speed timing is supported | 27 | - cap-sd-highspeed: SD high-speed timing is supported |
| 28 | - cap-mmc-highspeed: MMC high-speed timing is supported | 28 | - cap-mmc-highspeed: MMC high-speed timing is supported |
| 29 | - sd-uhs-sdr12: SD UHS SDR12 speed is supported | ||
| 30 | - sd-uhs-sdr25: SD UHS SDR25 speed is supported | ||
| 31 | - sd-uhs-sdr50: SD UHS SDR50 speed is supported | ||
| 32 | - sd-uhs-sdr104: SD UHS SDR104 speed is supported | ||
| 33 | - sd-uhs-ddr50: SD UHS DDR50 speed is supported | ||
| 29 | - cap-power-off-card: powering off the card is safe | 34 | - cap-power-off-card: powering off the card is safe |
| 30 | - cap-sdio-irq: enable SDIO IRQ signalling on this interface | 35 | - cap-sdio-irq: enable SDIO IRQ signalling on this interface |
| 31 | - full-pwr-cycle: full power cycle of the card is supported | 36 | - full-pwr-cycle: full power cycle of the card is supported |
| 37 | - mmc-highspeed-ddr-1_8v: eMMC high-speed DDR mode(1.8V I/O) is supported | ||
| 38 | - mmc-highspeed-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported | ||
| 39 | - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported | ||
| 40 | - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported | ||
| 32 | 41 | ||
| 33 | *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line | 42 | *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line |
| 34 | polarity properties, we have to fix the meaning of the "normal" and "inverted" | 43 | polarity properties, we have to fix the meaning of the "normal" and "inverted" |
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt new file mode 100644 index 000000000000..81b33b5b20fc --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | * Qualcomm SDHCI controller (sdhci-msm) | ||
| 2 | |||
| 3 | This file documents differences between the core properties in mmc.txt | ||
| 4 | and the properties used by the sdhci-msm driver. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | - compatible: Should contain "qcom,sdhci-msm-v4". | ||
| 8 | - reg: Base address and length of the register in the following order: | ||
| 9 | - Host controller register map (required) | ||
| 10 | - SD Core register map (required) | ||
| 11 | - interrupts: Should contain an interrupt-specifiers for the interrupts: | ||
| 12 | - Host controller interrupt (required) | ||
| 13 | - pinctrl-names: Should contain only one value - "default". | ||
| 14 | - pinctrl-0: Should specify pin control groups used for this controller. | ||
| 15 | - clocks: A list of phandle + clock-specifier pairs for the clocks listed in clock-names. | ||
| 16 | - clock-names: Should contain the following: | ||
| 17 | "iface" - Main peripheral bus clock (PCLK/HCLK - AHB Bus clock) (required) | ||
| 18 | "core" - SDC MMC clock (MCLK) (required) | ||
| 19 | "bus" - SDCC bus voter clock (optional) | ||
| 20 | |||
| 21 | Example: | ||
| 22 | |||
| 23 | sdhc_1: sdhci@f9824900 { | ||
| 24 | compatible = "qcom,sdhci-msm-v4"; | ||
| 25 | reg = <0xf9824900 0x11c>, <0xf9824000 0x800>; | ||
| 26 | interrupts = <0 123 0>; | ||
| 27 | bus-width = <8>; | ||
| 28 | non-removable; | ||
| 29 | |||
| 30 | vmmc = <&pm8941_l20>; | ||
| 31 | vqmmc = <&pm8941_s3>; | ||
| 32 | |||
| 33 | pinctrl-names = "default"; | ||
| 34 | pinctrl-0 = <&sdc1_clk &sdc1_cmd &sdc1_data>; | ||
| 35 | |||
| 36 | clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>; | ||
| 37 | clock-names = "core", "iface"; | ||
| 38 | }; | ||
| 39 | |||
| 40 | sdhc_2: sdhci@f98a4900 { | ||
| 41 | compatible = "qcom,sdhci-msm-v4"; | ||
| 42 | reg = <0xf98a4900 0x11c>, <0xf98a4000 0x800>; | ||
| 43 | interrupts = <0 125 0>; | ||
| 44 | bus-width = <4>; | ||
| 45 | cd-gpios = <&msmgpio 62 0x1>; | ||
| 46 | |||
| 47 | vmmc = <&pm8941_l21>; | ||
| 48 | vqmmc = <&pm8941_l13>; | ||
| 49 | |||
| 50 | pinctrl-names = "default"; | ||
| 51 | pinctrl-0 = <&sdc2_clk &sdc2_cmd &sdc2_data>; | ||
| 52 | |||
| 53 | clocks = <&gcc GCC_SDCC2_APPS_CLK>, <&gcc GCC_SDCC2_AHB_CLK>; | ||
| 54 | clock-names = "core", "iface"; | ||
| 55 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt b/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt index dbe98a3c183a..86223c3eda90 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt +++ b/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt | |||
| @@ -4,7 +4,14 @@ This file documents differences between the core properties in mmc.txt | |||
| 4 | and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers. | 4 | and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers. |
| 5 | 5 | ||
| 6 | Required properties: | 6 | Required properties: |
| 7 | - compatible: Should be "mrvl,pxav2-mmc" or "mrvl,pxav3-mmc". | 7 | - compatible: Should be "mrvl,pxav2-mmc", "mrvl,pxav3-mmc" or |
| 8 | "marvell,armada-380-sdhci". | ||
| 9 | - reg: | ||
| 10 | * for "mrvl,pxav2-mmc" and "mrvl,pxav3-mmc", one register area for | ||
| 11 | the SDHCI registers. | ||
| 12 | * for "marvell,armada-380-sdhci", two register areas. The first one | ||
| 13 | for the SDHCI registers themselves, and the second one for the | ||
| 14 | AXI/Mbus bridge registers of the SDHCI unit. | ||
| 8 | 15 | ||
| 9 | Optional properties: | 16 | Optional properties: |
| 10 | - mrvl,clk-delay-cycles: Specify a number of cycles to delay for tuning. | 17 | - mrvl,clk-delay-cycles: Specify a number of cycles to delay for tuning. |
| @@ -19,3 +26,11 @@ sdhci@d4280800 { | |||
| 19 | non-removable; | 26 | non-removable; |
| 20 | mrvl,clk-delay-cycles = <31>; | 27 | mrvl,clk-delay-cycles = <31>; |
| 21 | }; | 28 | }; |
| 29 | |||
| 30 | sdhci@d8000 { | ||
| 31 | compatible = "marvell,armada-380-sdhci"; | ||
| 32 | reg = <0xd8000 0x1000>, <0xdc000 0x100>; | ||
| 33 | interrupts = <0 25 0x4>; | ||
| 34 | clocks = <&gateclk 17>; | ||
| 35 | mrvl,clk-delay-cycles = <0x1F>; | ||
| 36 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt index 8c8908ab84ba..ce8056116fb0 100644 --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt | |||
| @@ -10,6 +10,7 @@ Required properties: | |||
| 10 | - compatible: | 10 | - compatible: |
| 11 | Should be "ti,omap2-hsmmc", for OMAP2 controllers | 11 | Should be "ti,omap2-hsmmc", for OMAP2 controllers |
| 12 | Should be "ti,omap3-hsmmc", for OMAP3 controllers | 12 | Should be "ti,omap3-hsmmc", for OMAP3 controllers |
| 13 | Should be "ti,omap3-pre-es3-hsmmc" for OMAP3 controllers pre ES3.0 | ||
| 13 | Should be "ti,omap4-hsmmc", for OMAP4 controllers | 14 | Should be "ti,omap4-hsmmc", for OMAP4 controllers |
| 14 | - ti,hwmods: Must be "mmc<n>", n is controller instance starting 1 | 15 | - ti,hwmods: Must be "mmc<n>", n is controller instance starting 1 |
| 15 | 16 | ||
diff --git a/Documentation/devicetree/bindings/regulator/pbias-regulator.txt b/Documentation/devicetree/bindings/regulator/pbias-regulator.txt new file mode 100644 index 000000000000..32aa26f1e434 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/pbias-regulator.txt | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | PBIAS internal regulator for SD card dual voltage i/o pads on OMAP SoCs. | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: | ||
| 5 | - "ti,pbias-omap" for OMAP2, OMAP3, OMAP4, OMAP5, DRA7. | ||
| 6 | - reg: pbias register offset from syscon base and size of pbias register. | ||
| 7 | - syscon : phandle of the system control module | ||
| 8 | - regulator-name : should be | ||
| 9 | pbias_mmc_omap2430 for OMAP2430, OMAP3 SoCs | ||
| 10 | pbias_sim_omap3 for OMAP3 SoCs | ||
| 11 | pbias_mmc_omap4 for OMAP4 SoCs | ||
| 12 | pbias_mmc_omap5 for OMAP5 and DRA7 SoC | ||
| 13 | |||
| 14 | Optional properties: | ||
| 15 | - Any optional property defined in bindings/regulator/regulator.txt | ||
| 16 | |||
| 17 | Example: | ||
| 18 | |||
| 19 | pbias_regulator: pbias_regulator { | ||
| 20 | compatible = "ti,pbias-omap"; | ||
| 21 | reg = <0 0x4>; | ||
| 22 | syscon = <&omap5_padconf_global>; | ||
| 23 | pbias_mmc_reg: pbias_mmc_omap5 { | ||
| 24 | regulator-name = "pbias_mmc_omap5"; | ||
| 25 | regulator-min-microvolt = <1800000>; | ||
| 26 | regulator-max-microvolt = <3000000>; | ||
| 27 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 7faf31001437..a769432bddbe 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -5930,6 +5930,7 @@ F: include/linux/mfd/ | |||
| 5930 | 5930 | ||
| 5931 | MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM | 5931 | MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM |
| 5932 | M: Chris Ball <chris@printf.net> | 5932 | M: Chris Ball <chris@printf.net> |
| 5933 | M: Ulf Hansson <ulf.hansson@linaro.org> | ||
| 5933 | L: linux-mmc@vger.kernel.org | 5934 | L: linux-mmc@vger.kernel.org |
| 5934 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git | 5935 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git |
| 5935 | S: Maintained | 5936 | S: Maintained |
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 9e3caf3d19fb..1c0f8e1893ae 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi | |||
| @@ -154,6 +154,22 @@ | |||
| 154 | ti,hwmods = "counter_32k"; | 154 | ti,hwmods = "counter_32k"; |
| 155 | }; | 155 | }; |
| 156 | 156 | ||
| 157 | dra7_ctrl_general: tisyscon@4a002e00 { | ||
| 158 | compatible = "syscon"; | ||
| 159 | reg = <0x4a002e00 0x7c>; | ||
| 160 | }; | ||
| 161 | |||
| 162 | pbias_regulator: pbias_regulator { | ||
| 163 | compatible = "ti,pbias-omap"; | ||
| 164 | reg = <0 0x4>; | ||
| 165 | syscon = <&dra7_ctrl_general>; | ||
| 166 | pbias_mmc_reg: pbias_mmc_omap5 { | ||
| 167 | regulator-name = "pbias_mmc_omap5"; | ||
| 168 | regulator-min-microvolt = <1800000>; | ||
| 169 | regulator-max-microvolt = <3000000>; | ||
| 170 | }; | ||
| 171 | }; | ||
| 172 | |||
| 157 | dra7_pmx_core: pinmux@4a003400 { | 173 | dra7_pmx_core: pinmux@4a003400 { |
| 158 | compatible = "pinctrl-single"; | 174 | compatible = "pinctrl-single"; |
| 159 | reg = <0x4a003400 0x0464>; | 175 | reg = <0x4a003400 0x0464>; |
| @@ -543,6 +559,7 @@ | |||
| 543 | dmas = <&sdma 61>, <&sdma 62>; | 559 | dmas = <&sdma 61>, <&sdma 62>; |
| 544 | dma-names = "tx", "rx"; | 560 | dma-names = "tx", "rx"; |
| 545 | status = "disabled"; | 561 | status = "disabled"; |
| 562 | pbias-supply = <&pbias_mmc_reg>; | ||
| 546 | }; | 563 | }; |
| 547 | 564 | ||
| 548 | mmc2: mmc@480b4000 { | 565 | mmc2: mmc@480b4000 { |
diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi index 9d2f028fd687..d09697dab55e 100644 --- a/arch/arm/boot/dts/omap2430.dtsi +++ b/arch/arm/boot/dts/omap2430.dtsi | |||
| @@ -29,6 +29,22 @@ | |||
| 29 | pinctrl-single,function-mask = <0x3f>; | 29 | pinctrl-single,function-mask = <0x3f>; |
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | omap2_scm_general: tisyscon@49002270 { | ||
| 33 | compatible = "syscon"; | ||
| 34 | reg = <0x49002270 0x240>; | ||
| 35 | }; | ||
| 36 | |||
| 37 | pbias_regulator: pbias_regulator { | ||
| 38 | compatible = "ti,pbias-omap"; | ||
| 39 | reg = <0x230 0x4>; | ||
| 40 | syscon = <&omap2_scm_general>; | ||
| 41 | pbias_mmc_reg: pbias_mmc_omap2430 { | ||
| 42 | regulator-name = "pbias_mmc_omap2430"; | ||
| 43 | regulator-min-microvolt = <1800000>; | ||
| 44 | regulator-max-microvolt = <3000000>; | ||
| 45 | }; | ||
| 46 | }; | ||
| 47 | |||
| 32 | gpio1: gpio@4900c000 { | 48 | gpio1: gpio@4900c000 { |
| 33 | compatible = "ti,omap2-gpio"; | 49 | compatible = "ti,omap2-gpio"; |
| 34 | reg = <0x4900c000 0x200>; | 50 | reg = <0x4900c000 0x200>; |
| @@ -188,6 +204,7 @@ | |||
| 188 | ti,dual-volt; | 204 | ti,dual-volt; |
| 189 | dmas = <&sdma 61>, <&sdma 62>; | 205 | dmas = <&sdma 61>, <&sdma 62>; |
| 190 | dma-names = "tx", "rx"; | 206 | dma-names = "tx", "rx"; |
| 207 | pbias-supply = <&pbias_mmc_reg>; | ||
| 191 | }; | 208 | }; |
| 192 | 209 | ||
| 193 | mmc2: mmc@480b4000 { | 210 | mmc2: mmc@480b4000 { |
diff --git a/arch/arm/boot/dts/omap3-ldp.dts b/arch/arm/boot/dts/omap3-ldp.dts index ddce0d807f70..0abe986a4ecc 100644 --- a/arch/arm/boot/dts/omap3-ldp.dts +++ b/arch/arm/boot/dts/omap3-ldp.dts | |||
| @@ -174,8 +174,20 @@ | |||
| 174 | }; | 174 | }; |
| 175 | 175 | ||
| 176 | &mmc1 { | 176 | &mmc1 { |
| 177 | /* See 35xx errata 2.1.1.128 in SPRZ278F */ | ||
| 178 | compatible = "ti,omap3-pre-es3-hsmmc"; | ||
| 177 | vmmc-supply = <&vmmc1>; | 179 | vmmc-supply = <&vmmc1>; |
| 178 | bus-width = <4>; | 180 | bus-width = <4>; |
| 181 | pinctrl-names = "default"; | ||
| 182 | pinctrl-0 = <&mmc1_pins>; | ||
| 183 | }; | ||
| 184 | |||
| 185 | &mmc2 { | ||
| 186 | status="disabled"; | ||
| 187 | }; | ||
| 188 | |||
| 189 | &mmc3 { | ||
| 190 | status="disabled"; | ||
| 179 | }; | 191 | }; |
| 180 | 192 | ||
| 181 | &omap3_pmx_core { | 193 | &omap3_pmx_core { |
| @@ -209,6 +221,17 @@ | |||
| 209 | 0x174 (PIN_OUTPUT | MUX_MODE0) /* hsusb0_stp.hsusb0_stp */ | 221 | 0x174 (PIN_OUTPUT | MUX_MODE0) /* hsusb0_stp.hsusb0_stp */ |
| 210 | >; | 222 | >; |
| 211 | }; | 223 | }; |
| 224 | |||
| 225 | mmc1_pins: pinmux_mmc1_pins { | ||
| 226 | pinctrl-single,pins = < | ||
| 227 | OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.mmc1_clk */ | ||
| 228 | OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.mmc1_cmd */ | ||
| 229 | OMAP3_CORE1_IOPAD(0x2148, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.mmc1_dat0 */ | ||
| 230 | OMAP3_CORE1_IOPAD(0x214A, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.mmc1_dat1 */ | ||
| 231 | OMAP3_CORE1_IOPAD(0x214C, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.mmc1_dat2 */ | ||
| 232 | OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.mmc1_dat3 */ | ||
| 233 | >; | ||
| 234 | }; | ||
| 212 | }; | 235 | }; |
| 213 | 236 | ||
| 214 | &usb_otg_hs { | 237 | &usb_otg_hs { |
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi index 3d05eff67e25..5e5790f631eb 100644 --- a/arch/arm/boot/dts/omap3.dtsi +++ b/arch/arm/boot/dts/omap3.dtsi | |||
| @@ -181,6 +181,22 @@ | |||
| 181 | pinctrl-single,function-mask = <0xff1f>; | 181 | pinctrl-single,function-mask = <0xff1f>; |
| 182 | }; | 182 | }; |
| 183 | 183 | ||
| 184 | omap3_scm_general: tisyscon@48002270 { | ||
| 185 | compatible = "syscon"; | ||
| 186 | reg = <0x48002270 0x2f0>; | ||
| 187 | }; | ||
| 188 | |||
| 189 | pbias_regulator: pbias_regulator { | ||
| 190 | compatible = "ti,pbias-omap"; | ||
| 191 | reg = <0x2b0 0x4>; | ||
| 192 | syscon = <&omap3_scm_general>; | ||
| 193 | pbias_mmc_reg: pbias_mmc_omap2430 { | ||
| 194 | regulator-name = "pbias_mmc_omap2430"; | ||
| 195 | regulator-min-microvolt = <1800000>; | ||
| 196 | regulator-max-microvolt = <3000000>; | ||
| 197 | }; | ||
| 198 | }; | ||
| 199 | |||
| 184 | gpio1: gpio@48310000 { | 200 | gpio1: gpio@48310000 { |
| 185 | compatible = "ti,omap3-gpio"; | 201 | compatible = "ti,omap3-gpio"; |
| 186 | reg = <0x48310000 0x200>; | 202 | reg = <0x48310000 0x200>; |
| @@ -395,6 +411,7 @@ | |||
| 395 | ti,dual-volt; | 411 | ti,dual-volt; |
| 396 | dmas = <&sdma 61>, <&sdma 62>; | 412 | dmas = <&sdma 61>, <&sdma 62>; |
| 397 | dma-names = "tx", "rx"; | 413 | dma-names = "tx", "rx"; |
| 414 | pbias-supply = <&pbias_mmc_reg>; | ||
| 398 | }; | 415 | }; |
| 399 | 416 | ||
| 400 | mmc2: mmc@480b4000 { | 417 | mmc2: mmc@480b4000 { |
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 2b4c1cbbce33..27fcac874742 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi | |||
| @@ -191,6 +191,22 @@ | |||
| 191 | pinctrl-single,function-mask = <0x7fff>; | 191 | pinctrl-single,function-mask = <0x7fff>; |
| 192 | }; | 192 | }; |
| 193 | 193 | ||
| 194 | omap4_padconf_global: tisyscon@4a1005a0 { | ||
| 195 | compatible = "syscon"; | ||
| 196 | reg = <0x4a1005a0 0x170>; | ||
| 197 | }; | ||
| 198 | |||
| 199 | pbias_regulator: pbias_regulator { | ||
| 200 | compatible = "ti,pbias-omap"; | ||
| 201 | reg = <0x60 0x4>; | ||
| 202 | syscon = <&omap4_padconf_global>; | ||
| 203 | pbias_mmc_reg: pbias_mmc_omap4 { | ||
| 204 | regulator-name = "pbias_mmc_omap4"; | ||
| 205 | regulator-min-microvolt = <1800000>; | ||
| 206 | regulator-max-microvolt = <3000000>; | ||
| 207 | }; | ||
| 208 | }; | ||
| 209 | |||
| 194 | sdma: dma-controller@4a056000 { | 210 | sdma: dma-controller@4a056000 { |
| 195 | compatible = "ti,omap4430-sdma"; | 211 | compatible = "ti,omap4430-sdma"; |
| 196 | reg = <0x4a056000 0x1000>; | 212 | reg = <0x4a056000 0x1000>; |
| @@ -427,6 +443,7 @@ | |||
| 427 | ti,needs-special-reset; | 443 | ti,needs-special-reset; |
| 428 | dmas = <&sdma 61>, <&sdma 62>; | 444 | dmas = <&sdma 61>, <&sdma 62>; |
| 429 | dma-names = "tx", "rx"; | 445 | dma-names = "tx", "rx"; |
| 446 | pbias-supply = <&pbias_mmc_reg>; | ||
| 430 | }; | 447 | }; |
| 431 | 448 | ||
| 432 | mmc2: mmc@480b4000 { | 449 | mmc2: mmc@480b4000 { |
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 19155bb84835..6f3de22fb266 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi | |||
| @@ -198,6 +198,22 @@ | |||
| 198 | pinctrl-single,function-mask = <0x7fff>; | 198 | pinctrl-single,function-mask = <0x7fff>; |
| 199 | }; | 199 | }; |
| 200 | 200 | ||
| 201 | omap5_padconf_global: tisyscon@4a002da0 { | ||
| 202 | compatible = "syscon"; | ||
| 203 | reg = <0x4A002da0 0xec>; | ||
| 204 | }; | ||
| 205 | |||
| 206 | pbias_regulator: pbias_regulator { | ||
| 207 | compatible = "ti,pbias-omap"; | ||
| 208 | reg = <0x60 0x4>; | ||
| 209 | syscon = <&omap5_padconf_global>; | ||
| 210 | pbias_mmc_reg: pbias_mmc_omap5 { | ||
| 211 | regulator-name = "pbias_mmc_omap5"; | ||
| 212 | regulator-min-microvolt = <1800000>; | ||
| 213 | regulator-max-microvolt = <3000000>; | ||
| 214 | }; | ||
| 215 | }; | ||
| 216 | |||
| 201 | sdma: dma-controller@4a056000 { | 217 | sdma: dma-controller@4a056000 { |
| 202 | compatible = "ti,omap4430-sdma"; | 218 | compatible = "ti,omap4430-sdma"; |
| 203 | reg = <0x4a056000 0x1000>; | 219 | reg = <0x4a056000 0x1000>; |
| @@ -480,6 +496,7 @@ | |||
| 480 | ti,needs-special-reset; | 496 | ti,needs-special-reset; |
| 481 | dmas = <&sdma 61>, <&sdma 62>; | 497 | dmas = <&sdma 61>, <&sdma 62>; |
| 482 | dma-names = "tx", "rx"; | 498 | dma-names = "tx", "rx"; |
| 499 | pbias-supply = <&pbias_mmc_reg>; | ||
| 483 | }; | 500 | }; |
| 484 | 501 | ||
| 485 | mmc2: mmc@480b4000 { | 502 | mmc2: mmc@480b4000 { |
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 364ba38e40f3..a9667957b757 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig | |||
| @@ -170,6 +170,7 @@ CONFIG_DRA752_THERMAL=y | |||
| 170 | CONFIG_WATCHDOG=y | 170 | CONFIG_WATCHDOG=y |
| 171 | CONFIG_OMAP_WATCHDOG=y | 171 | CONFIG_OMAP_WATCHDOG=y |
| 172 | CONFIG_TWL4030_WATCHDOG=y | 172 | CONFIG_TWL4030_WATCHDOG=y |
| 173 | CONFIG_MFD_SYSCON=y | ||
| 173 | CONFIG_MFD_PALMAS=y | 174 | CONFIG_MFD_PALMAS=y |
| 174 | CONFIG_MFD_TPS65217=y | 175 | CONFIG_MFD_TPS65217=y |
| 175 | CONFIG_MFD_TPS65910=y | 176 | CONFIG_MFD_TPS65910=y |
| @@ -181,6 +182,7 @@ CONFIG_REGULATOR_TPS6507X=y | |||
| 181 | CONFIG_REGULATOR_TPS65217=y | 182 | CONFIG_REGULATOR_TPS65217=y |
| 182 | CONFIG_REGULATOR_TPS65910=y | 183 | CONFIG_REGULATOR_TPS65910=y |
| 183 | CONFIG_REGULATOR_TWL4030=y | 184 | CONFIG_REGULATOR_TWL4030=y |
| 185 | CONFIG_REGULATOR_PBIAS=y | ||
| 184 | CONFIG_FB=y | 186 | CONFIG_FB=y |
| 185 | CONFIG_FIRMWARE_EDID=y | 187 | CONFIG_FIRMWARE_EDID=y |
| 186 | CONFIG_FB_MODE_HELPERS=y | 188 | CONFIG_FB_MODE_HELPERS=y |
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 1d15735f9ef9..c9de3d598ea5 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c | |||
| @@ -338,58 +338,28 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, | |||
| 338 | int num_sg, bool read, int timeout) | 338 | int num_sg, bool read, int timeout) |
| 339 | { | 339 | { |
| 340 | struct completion trans_done; | 340 | struct completion trans_done; |
| 341 | u8 dir; | 341 | int err = 0, count; |
| 342 | int err = 0, i, count; | ||
| 343 | long timeleft; | 342 | long timeleft; |
| 344 | unsigned long flags; | 343 | unsigned long flags; |
| 345 | struct scatterlist *sg; | ||
| 346 | enum dma_data_direction dma_dir; | ||
| 347 | u32 val; | ||
| 348 | dma_addr_t addr; | ||
| 349 | unsigned int len; | ||
| 350 | |||
| 351 | dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg); | ||
| 352 | |||
| 353 | /* don't transfer data during abort processing */ | ||
| 354 | if (pcr->remove_pci) | ||
| 355 | return -EINVAL; | ||
| 356 | |||
| 357 | if ((sglist == NULL) || (num_sg <= 0)) | ||
| 358 | return -EINVAL; | ||
| 359 | 344 | ||
| 360 | if (read) { | 345 | count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read); |
| 361 | dir = DEVICE_TO_HOST; | ||
| 362 | dma_dir = DMA_FROM_DEVICE; | ||
| 363 | } else { | ||
| 364 | dir = HOST_TO_DEVICE; | ||
| 365 | dma_dir = DMA_TO_DEVICE; | ||
| 366 | } | ||
| 367 | |||
| 368 | count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); | ||
| 369 | if (count < 1) { | 346 | if (count < 1) { |
| 370 | dev_err(&(pcr->pci->dev), "scatterlist map failed\n"); | 347 | dev_err(&(pcr->pci->dev), "scatterlist map failed\n"); |
| 371 | return -EINVAL; | 348 | return -EINVAL; |
| 372 | } | 349 | } |
| 373 | dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count); | 350 | dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count); |
| 374 | 351 | ||
| 375 | val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE; | ||
| 376 | pcr->sgi = 0; | ||
| 377 | for_each_sg(sglist, sg, count, i) { | ||
| 378 | addr = sg_dma_address(sg); | ||
| 379 | len = sg_dma_len(sg); | ||
| 380 | rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1); | ||
| 381 | } | ||
| 382 | 352 | ||
| 383 | spin_lock_irqsave(&pcr->lock, flags); | 353 | spin_lock_irqsave(&pcr->lock, flags); |
| 384 | 354 | ||
| 385 | pcr->done = &trans_done; | 355 | pcr->done = &trans_done; |
| 386 | pcr->trans_result = TRANS_NOT_READY; | 356 | pcr->trans_result = TRANS_NOT_READY; |
| 387 | init_completion(&trans_done); | 357 | init_completion(&trans_done); |
| 388 | rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr); | ||
| 389 | rtsx_pci_writel(pcr, RTSX_HDBCTLR, val); | ||
| 390 | 358 | ||
| 391 | spin_unlock_irqrestore(&pcr->lock, flags); | 359 | spin_unlock_irqrestore(&pcr->lock, flags); |
| 392 | 360 | ||
| 361 | rtsx_pci_dma_transfer(pcr, sglist, count, read); | ||
| 362 | |||
| 393 | timeleft = wait_for_completion_interruptible_timeout( | 363 | timeleft = wait_for_completion_interruptible_timeout( |
| 394 | &trans_done, msecs_to_jiffies(timeout)); | 364 | &trans_done, msecs_to_jiffies(timeout)); |
| 395 | if (timeleft <= 0) { | 365 | if (timeleft <= 0) { |
| @@ -413,7 +383,7 @@ out: | |||
| 413 | pcr->done = NULL; | 383 | pcr->done = NULL; |
| 414 | spin_unlock_irqrestore(&pcr->lock, flags); | 384 | spin_unlock_irqrestore(&pcr->lock, flags); |
| 415 | 385 | ||
| 416 | dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); | 386 | rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read); |
| 417 | 387 | ||
| 418 | if ((err < 0) && (err != -ENODEV)) | 388 | if ((err < 0) && (err != -ENODEV)) |
| 419 | rtsx_pci_stop_cmd(pcr); | 389 | rtsx_pci_stop_cmd(pcr); |
| @@ -425,6 +395,73 @@ out: | |||
| 425 | } | 395 | } |
| 426 | EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data); | 396 | EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data); |
| 427 | 397 | ||
| 398 | int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
| 399 | int num_sg, bool read) | ||
| 400 | { | ||
| 401 | enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
| 402 | |||
| 403 | if (pcr->remove_pci) | ||
| 404 | return -EINVAL; | ||
| 405 | |||
| 406 | if ((sglist == NULL) || num_sg < 1) | ||
| 407 | return -EINVAL; | ||
| 408 | |||
| 409 | return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir); | ||
| 410 | } | ||
| 411 | EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg); | ||
| 412 | |||
| 413 | int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
| 414 | int num_sg, bool read) | ||
| 415 | { | ||
| 416 | enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
| 417 | |||
| 418 | if (pcr->remove_pci) | ||
| 419 | return -EINVAL; | ||
| 420 | |||
| 421 | if (sglist == NULL || num_sg < 1) | ||
| 422 | return -EINVAL; | ||
| 423 | |||
| 424 | dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir); | ||
| 425 | return num_sg; | ||
| 426 | } | ||
| 427 | EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg); | ||
| 428 | |||
| 429 | int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
| 430 | int sg_count, bool read) | ||
| 431 | { | ||
| 432 | struct scatterlist *sg; | ||
| 433 | dma_addr_t addr; | ||
| 434 | unsigned int len; | ||
| 435 | int i; | ||
| 436 | u32 val; | ||
| 437 | u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE; | ||
| 438 | unsigned long flags; | ||
| 439 | |||
| 440 | if (pcr->remove_pci) | ||
| 441 | return -EINVAL; | ||
| 442 | |||
| 443 | if ((sglist == NULL) || (sg_count < 1)) | ||
| 444 | return -EINVAL; | ||
| 445 | |||
| 446 | val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE; | ||
| 447 | pcr->sgi = 0; | ||
| 448 | for_each_sg(sglist, sg, sg_count, i) { | ||
| 449 | addr = sg_dma_address(sg); | ||
| 450 | len = sg_dma_len(sg); | ||
| 451 | rtsx_pci_add_sg_tbl(pcr, addr, len, i == sg_count - 1); | ||
| 452 | } | ||
| 453 | |||
| 454 | spin_lock_irqsave(&pcr->lock, flags); | ||
| 455 | |||
| 456 | rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr); | ||
| 457 | rtsx_pci_writel(pcr, RTSX_HDBCTLR, val); | ||
| 458 | |||
| 459 | spin_unlock_irqrestore(&pcr->lock, flags); | ||
| 460 | |||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer); | ||
| 464 | |||
| 428 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len) | 465 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len) |
| 429 | { | 466 | { |
| 430 | int err; | 467 | int err; |
| @@ -836,6 +873,8 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) | |||
| 836 | int_reg = rtsx_pci_readl(pcr, RTSX_BIPR); | 873 | int_reg = rtsx_pci_readl(pcr, RTSX_BIPR); |
| 837 | /* Clear interrupt flag */ | 874 | /* Clear interrupt flag */ |
| 838 | rtsx_pci_writel(pcr, RTSX_BIPR, int_reg); | 875 | rtsx_pci_writel(pcr, RTSX_BIPR, int_reg); |
| 876 | dev_dbg(&pcr->pci->dev, "=========== BIPR 0x%8x ==========\n", int_reg); | ||
| 877 | |||
| 839 | if ((int_reg & pcr->bier) == 0) { | 878 | if ((int_reg & pcr->bier) == 0) { |
| 840 | spin_unlock(&pcr->lock); | 879 | spin_unlock(&pcr->lock); |
| 841 | return IRQ_NONE; | 880 | return IRQ_NONE; |
| @@ -866,17 +905,28 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) | |||
| 866 | } | 905 | } |
| 867 | 906 | ||
| 868 | if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) { | 907 | if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) { |
| 869 | if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) { | 908 | if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) |
| 870 | pcr->trans_result = TRANS_RESULT_FAIL; | 909 | pcr->trans_result = TRANS_RESULT_FAIL; |
| 871 | if (pcr->done) | 910 | else if (int_reg & TRANS_OK_INT) |
| 872 | complete(pcr->done); | ||
| 873 | } else if (int_reg & TRANS_OK_INT) { | ||
| 874 | pcr->trans_result = TRANS_RESULT_OK; | 911 | pcr->trans_result = TRANS_RESULT_OK; |
| 875 | if (pcr->done) | 912 | |
| 876 | complete(pcr->done); | 913 | if (pcr->done) |
| 914 | complete(pcr->done); | ||
| 915 | |||
| 916 | if (int_reg & SD_EXIST) { | ||
| 917 | struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD]; | ||
| 918 | if (slot && slot->done_transfer) | ||
| 919 | slot->done_transfer(slot->p_dev); | ||
| 920 | } | ||
| 921 | |||
| 922 | if (int_reg & MS_EXIST) { | ||
| 923 | struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD]; | ||
| 924 | if (slot && slot->done_transfer) | ||
| 925 | slot->done_transfer(slot->p_dev); | ||
| 877 | } | 926 | } |
| 878 | } | 927 | } |
| 879 | 928 | ||
| 929 | |||
| 880 | if (pcr->card_inserted || pcr->card_removed) | 930 | if (pcr->card_inserted || pcr->card_removed) |
| 881 | schedule_delayed_work(&pcr->carddet_work, | 931 | schedule_delayed_work(&pcr->carddet_work, |
| 882 | msecs_to_jiffies(200)); | 932 | msecs_to_jiffies(200)); |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 7b5424f398ac..452782bffebc 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
| @@ -415,8 +415,7 @@ static int ioctl_do_sanitize(struct mmc_card *card) | |||
| 415 | { | 415 | { |
| 416 | int err; | 416 | int err; |
| 417 | 417 | ||
| 418 | if (!(mmc_can_sanitize(card) && | 418 | if (!mmc_can_sanitize(card)) { |
| 419 | (card->host->caps2 & MMC_CAP2_SANITIZE))) { | ||
| 420 | pr_warn("%s: %s - SANITIZE is not supported\n", | 419 | pr_warn("%s: %s - SANITIZE is not supported\n", |
| 421 | mmc_hostname(card->host), __func__); | 420 | mmc_hostname(card->host), __func__); |
| 422 | err = -EOPNOTSUPP; | 421 | err = -EOPNOTSUPP; |
| @@ -722,19 +721,6 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card) | |||
| 722 | return result; | 721 | return result; |
| 723 | } | 722 | } |
| 724 | 723 | ||
| 725 | static int send_stop(struct mmc_card *card, u32 *status) | ||
| 726 | { | ||
| 727 | struct mmc_command cmd = {0}; | ||
| 728 | int err; | ||
| 729 | |||
| 730 | cmd.opcode = MMC_STOP_TRANSMISSION; | ||
| 731 | cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | ||
| 732 | err = mmc_wait_for_cmd(card->host, &cmd, 5); | ||
| 733 | if (err == 0) | ||
| 734 | *status = cmd.resp[0]; | ||
| 735 | return err; | ||
| 736 | } | ||
| 737 | |||
| 738 | static int get_card_status(struct mmc_card *card, u32 *status, int retries) | 724 | static int get_card_status(struct mmc_card *card, u32 *status, int retries) |
| 739 | { | 725 | { |
| 740 | struct mmc_command cmd = {0}; | 726 | struct mmc_command cmd = {0}; |
| @@ -750,6 +736,99 @@ static int get_card_status(struct mmc_card *card, u32 *status, int retries) | |||
| 750 | return err; | 736 | return err; |
| 751 | } | 737 | } |
| 752 | 738 | ||
| 739 | static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms, | ||
| 740 | bool hw_busy_detect, struct request *req, int *gen_err) | ||
| 741 | { | ||
| 742 | unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); | ||
| 743 | int err = 0; | ||
| 744 | u32 status; | ||
| 745 | |||
| 746 | do { | ||
| 747 | err = get_card_status(card, &status, 5); | ||
| 748 | if (err) { | ||
| 749 | pr_err("%s: error %d requesting status\n", | ||
| 750 | req->rq_disk->disk_name, err); | ||
| 751 | return err; | ||
| 752 | } | ||
| 753 | |||
| 754 | if (status & R1_ERROR) { | ||
| 755 | pr_err("%s: %s: error sending status cmd, status %#x\n", | ||
| 756 | req->rq_disk->disk_name, __func__, status); | ||
| 757 | *gen_err = 1; | ||
| 758 | } | ||
| 759 | |||
| 760 | /* We may rely on the host hw to handle busy detection.*/ | ||
| 761 | if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && | ||
| 762 | hw_busy_detect) | ||
| 763 | break; | ||
| 764 | |||
| 765 | /* | ||
| 766 | * Timeout if the device never becomes ready for data and never | ||
| 767 | * leaves the program state. | ||
| 768 | */ | ||
| 769 | if (time_after(jiffies, timeout)) { | ||
| 770 | pr_err("%s: Card stuck in programming state! %s %s\n", | ||
| 771 | mmc_hostname(card->host), | ||
| 772 | req->rq_disk->disk_name, __func__); | ||
| 773 | return -ETIMEDOUT; | ||
| 774 | } | ||
| 775 | |||
| 776 | /* | ||
| 777 | * Some cards mishandle the status bits, | ||
| 778 | * so make sure to check both the busy | ||
| 779 | * indication and the card state. | ||
| 780 | */ | ||
| 781 | } while (!(status & R1_READY_FOR_DATA) || | ||
| 782 | (R1_CURRENT_STATE(status) == R1_STATE_PRG)); | ||
| 783 | |||
| 784 | return err; | ||
| 785 | } | ||
| 786 | |||
| 787 | static int send_stop(struct mmc_card *card, unsigned int timeout_ms, | ||
| 788 | struct request *req, int *gen_err, u32 *stop_status) | ||
| 789 | { | ||
| 790 | struct mmc_host *host = card->host; | ||
| 791 | struct mmc_command cmd = {0}; | ||
| 792 | int err; | ||
| 793 | bool use_r1b_resp = rq_data_dir(req) == WRITE; | ||
| 794 | |||
| 795 | /* | ||
| 796 | * Normally we use R1B responses for WRITE, but in cases where the host | ||
| 797 | * has specified a max_busy_timeout we need to validate it. A failure | ||
| 798 | * means we need to prevent the host from doing hw busy detection, which | ||
| 799 | * is done by converting to a R1 response instead. | ||
| 800 | */ | ||
| 801 | if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) | ||
| 802 | use_r1b_resp = false; | ||
| 803 | |||
| 804 | cmd.opcode = MMC_STOP_TRANSMISSION; | ||
| 805 | if (use_r1b_resp) { | ||
| 806 | cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | ||
| 807 | cmd.busy_timeout = timeout_ms; | ||
| 808 | } else { | ||
| 809 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | ||
| 810 | } | ||
| 811 | |||
| 812 | err = mmc_wait_for_cmd(host, &cmd, 5); | ||
| 813 | if (err) | ||
| 814 | return err; | ||
| 815 | |||
| 816 | *stop_status = cmd.resp[0]; | ||
| 817 | |||
| 818 | /* No need to check card status in case of READ. */ | ||
| 819 | if (rq_data_dir(req) == READ) | ||
| 820 | return 0; | ||
| 821 | |||
| 822 | if (!mmc_host_is_spi(host) && | ||
| 823 | (*stop_status & R1_ERROR)) { | ||
| 824 | pr_err("%s: %s: general error sending stop command, resp %#x\n", | ||
| 825 | req->rq_disk->disk_name, __func__, *stop_status); | ||
| 826 | *gen_err = 1; | ||
| 827 | } | ||
| 828 | |||
| 829 | return card_busy_detect(card, timeout_ms, use_r1b_resp, req, gen_err); | ||
| 830 | } | ||
| 831 | |||
| 753 | #define ERR_NOMEDIUM 3 | 832 | #define ERR_NOMEDIUM 3 |
| 754 | #define ERR_RETRY 2 | 833 | #define ERR_RETRY 2 |
| 755 | #define ERR_ABORT 1 | 834 | #define ERR_ABORT 1 |
| @@ -866,26 +945,21 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, | |||
| 866 | */ | 945 | */ |
| 867 | if (R1_CURRENT_STATE(status) == R1_STATE_DATA || | 946 | if (R1_CURRENT_STATE(status) == R1_STATE_DATA || |
| 868 | R1_CURRENT_STATE(status) == R1_STATE_RCV) { | 947 | R1_CURRENT_STATE(status) == R1_STATE_RCV) { |
| 869 | err = send_stop(card, &stop_status); | 948 | err = send_stop(card, |
| 870 | if (err) | 949 | DIV_ROUND_UP(brq->data.timeout_ns, 1000000), |
| 950 | req, gen_err, &stop_status); | ||
| 951 | if (err) { | ||
| 871 | pr_err("%s: error %d sending stop command\n", | 952 | pr_err("%s: error %d sending stop command\n", |
| 872 | req->rq_disk->disk_name, err); | 953 | req->rq_disk->disk_name, err); |
| 873 | 954 | /* | |
| 874 | /* | 955 | * If the stop cmd also timed out, the card is probably |
| 875 | * If the stop cmd also timed out, the card is probably | 956 | * not present, so abort. Other errors are bad news too. |
| 876 | * not present, so abort. Other errors are bad news too. | 957 | */ |
| 877 | */ | ||
| 878 | if (err) | ||
| 879 | return ERR_ABORT; | 958 | return ERR_ABORT; |
| 959 | } | ||
| 960 | |||
| 880 | if (stop_status & R1_CARD_ECC_FAILED) | 961 | if (stop_status & R1_CARD_ECC_FAILED) |
| 881 | *ecc_err = 1; | 962 | *ecc_err = 1; |
| 882 | if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) | ||
| 883 | if (stop_status & R1_ERROR) { | ||
| 884 | pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n", | ||
| 885 | req->rq_disk->disk_name, __func__, | ||
| 886 | stop_status); | ||
| 887 | *gen_err = 1; | ||
| 888 | } | ||
| 889 | } | 963 | } |
| 890 | 964 | ||
| 891 | /* Check for set block count errors */ | 965 | /* Check for set block count errors */ |
| @@ -1157,8 +1231,7 @@ static int mmc_blk_err_check(struct mmc_card *card, | |||
| 1157 | * program mode, which we have to wait for it to complete. | 1231 | * program mode, which we have to wait for it to complete. |
| 1158 | */ | 1232 | */ |
| 1159 | if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { | 1233 | if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { |
| 1160 | u32 status; | 1234 | int err; |
| 1161 | unsigned long timeout; | ||
| 1162 | 1235 | ||
| 1163 | /* Check stop command response */ | 1236 | /* Check stop command response */ |
| 1164 | if (brq->stop.resp[0] & R1_ERROR) { | 1237 | if (brq->stop.resp[0] & R1_ERROR) { |
| @@ -1168,39 +1241,10 @@ static int mmc_blk_err_check(struct mmc_card *card, | |||
| 1168 | gen_err = 1; | 1241 | gen_err = 1; |
| 1169 | } | 1242 | } |
| 1170 | 1243 | ||
| 1171 | timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS); | 1244 | err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, false, req, |
| 1172 | do { | 1245 | &gen_err); |
| 1173 | int err = get_card_status(card, &status, 5); | 1246 | if (err) |
| 1174 | if (err) { | 1247 | return MMC_BLK_CMD_ERR; |
| 1175 | pr_err("%s: error %d requesting status\n", | ||
| 1176 | req->rq_disk->disk_name, err); | ||
| 1177 | return MMC_BLK_CMD_ERR; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | if (status & R1_ERROR) { | ||
| 1181 | pr_err("%s: %s: general error sending status command, card status %#x\n", | ||
| 1182 | req->rq_disk->disk_name, __func__, | ||
| 1183 | status); | ||
| 1184 | gen_err = 1; | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | /* Timeout if the device never becomes ready for data | ||
| 1188 | * and never leaves the program state. | ||
| 1189 | */ | ||
| 1190 | if (time_after(jiffies, timeout)) { | ||
| 1191 | pr_err("%s: Card stuck in programming state!"\ | ||
| 1192 | " %s %s\n", mmc_hostname(card->host), | ||
| 1193 | req->rq_disk->disk_name, __func__); | ||
| 1194 | |||
| 1195 | return MMC_BLK_CMD_ERR; | ||
| 1196 | } | ||
| 1197 | /* | ||
| 1198 | * Some cards mishandle the status bits, | ||
| 1199 | * so make sure to check both the busy | ||
| 1200 | * indication and the card state. | ||
| 1201 | */ | ||
| 1202 | } while (!(status & R1_READY_FOR_DATA) || | ||
| 1203 | (R1_CURRENT_STATE(status) == R1_STATE_PRG)); | ||
| 1204 | } | 1248 | } |
| 1205 | 1249 | ||
| 1206 | /* if general error occurs, retry the write operation. */ | 1250 | /* if general error occurs, retry the write operation. */ |
| @@ -1335,7 +1379,6 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, | |||
| 1335 | brq->data.blksz = 512; | 1379 | brq->data.blksz = 512; |
| 1336 | brq->stop.opcode = MMC_STOP_TRANSMISSION; | 1380 | brq->stop.opcode = MMC_STOP_TRANSMISSION; |
| 1337 | brq->stop.arg = 0; | 1381 | brq->stop.arg = 0; |
| 1338 | brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | ||
| 1339 | brq->data.blocks = blk_rq_sectors(req); | 1382 | brq->data.blocks = blk_rq_sectors(req); |
| 1340 | 1383 | ||
| 1341 | /* | 1384 | /* |
| @@ -1378,9 +1421,15 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, | |||
| 1378 | if (rq_data_dir(req) == READ) { | 1421 | if (rq_data_dir(req) == READ) { |
| 1379 | brq->cmd.opcode = readcmd; | 1422 | brq->cmd.opcode = readcmd; |
| 1380 | brq->data.flags |= MMC_DATA_READ; | 1423 | brq->data.flags |= MMC_DATA_READ; |
| 1424 | if (brq->mrq.stop) | ||
| 1425 | brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | | ||
| 1426 | MMC_CMD_AC; | ||
| 1381 | } else { | 1427 | } else { |
| 1382 | brq->cmd.opcode = writecmd; | 1428 | brq->cmd.opcode = writecmd; |
| 1383 | brq->data.flags |= MMC_DATA_WRITE; | 1429 | brq->data.flags |= MMC_DATA_WRITE; |
| 1430 | if (brq->mrq.stop) | ||
| 1431 | brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | | ||
| 1432 | MMC_CMD_AC; | ||
| 1384 | } | 1433 | } |
| 1385 | 1434 | ||
| 1386 | if (do_rel_wr) | 1435 | if (do_rel_wr) |
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index 269d072ef55e..9ebee72d9c3f 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig | |||
| @@ -2,21 +2,6 @@ | |||
| 2 | # MMC core configuration | 2 | # MMC core configuration |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | config MMC_UNSAFE_RESUME | ||
| 6 | bool "Assume MMC/SD cards are non-removable (DANGEROUS)" | ||
| 7 | help | ||
| 8 | If you say Y here, the MMC layer will assume that all cards | ||
| 9 | stayed in their respective slots during the suspend. The | ||
| 10 | normal behaviour is to remove them at suspend and | ||
| 11 | redetecting them at resume. Breaking this assumption will | ||
| 12 | in most cases result in data corruption. | ||
| 13 | |||
| 14 | This option is usually just for embedded systems which use | ||
| 15 | a MMC/SD card for rootfs. Most people should say N here. | ||
| 16 | |||
| 17 | This option sets a default which can be overridden by the | ||
| 18 | module parameter "removable=0" or "removable=1". | ||
| 19 | |||
| 20 | config MMC_CLKGATE | 5 | config MMC_CLKGATE |
| 21 | bool "MMC host clock gating" | 6 | bool "MMC host clock gating" |
| 22 | help | 7 | help |
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 64145a32b917..824644875d41 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
| @@ -185,24 +185,16 @@ static int mmc_runtime_suspend(struct device *dev) | |||
| 185 | { | 185 | { |
| 186 | struct mmc_card *card = mmc_dev_to_card(dev); | 186 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 187 | struct mmc_host *host = card->host; | 187 | struct mmc_host *host = card->host; |
| 188 | int ret = 0; | ||
| 189 | 188 | ||
| 190 | if (host->bus_ops->runtime_suspend) | 189 | return host->bus_ops->runtime_suspend(host); |
| 191 | ret = host->bus_ops->runtime_suspend(host); | ||
| 192 | |||
| 193 | return ret; | ||
| 194 | } | 190 | } |
| 195 | 191 | ||
| 196 | static int mmc_runtime_resume(struct device *dev) | 192 | static int mmc_runtime_resume(struct device *dev) |
| 197 | { | 193 | { |
| 198 | struct mmc_card *card = mmc_dev_to_card(dev); | 194 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 199 | struct mmc_host *host = card->host; | 195 | struct mmc_host *host = card->host; |
| 200 | int ret = 0; | ||
| 201 | 196 | ||
| 202 | if (host->bus_ops->runtime_resume) | 197 | return host->bus_ops->runtime_resume(host); |
| 203 | ret = host->bus_ops->runtime_resume(host); | ||
| 204 | |||
| 205 | return ret; | ||
| 206 | } | 198 | } |
| 207 | 199 | ||
| 208 | static int mmc_runtime_idle(struct device *dev) | 200 | static int mmc_runtime_idle(struct device *dev) |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 098374b1ab2b..acbc3f2aaaf9 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/mmc/host.h> | 34 | #include <linux/mmc/host.h> |
| 35 | #include <linux/mmc/mmc.h> | 35 | #include <linux/mmc/mmc.h> |
| 36 | #include <linux/mmc/sd.h> | 36 | #include <linux/mmc/sd.h> |
| 37 | #include <linux/mmc/slot-gpio.h> | ||
| 37 | 38 | ||
| 38 | #include "core.h" | 39 | #include "core.h" |
| 39 | #include "bus.h" | 40 | #include "bus.h" |
| @@ -65,23 +66,6 @@ bool use_spi_crc = 1; | |||
| 65 | module_param(use_spi_crc, bool, 0); | 66 | module_param(use_spi_crc, bool, 0); |
| 66 | 67 | ||
| 67 | /* | 68 | /* |
| 68 | * We normally treat cards as removed during suspend if they are not | ||
| 69 | * known to be on a non-removable bus, to avoid the risk of writing | ||
| 70 | * back data to a different card after resume. Allow this to be | ||
| 71 | * overridden if necessary. | ||
| 72 | */ | ||
| 73 | #ifdef CONFIG_MMC_UNSAFE_RESUME | ||
| 74 | bool mmc_assume_removable; | ||
| 75 | #else | ||
| 76 | bool mmc_assume_removable = 1; | ||
| 77 | #endif | ||
| 78 | EXPORT_SYMBOL(mmc_assume_removable); | ||
| 79 | module_param_named(removable, mmc_assume_removable, bool, 0644); | ||
| 80 | MODULE_PARM_DESC( | ||
| 81 | removable, | ||
| 82 | "MMC/SD cards are removable and may be removed during suspend"); | ||
| 83 | |||
| 84 | /* | ||
| 85 | * Internal function. Schedule delayed work in the MMC work queue. | 69 | * Internal function. Schedule delayed work in the MMC work queue. |
| 86 | */ | 70 | */ |
| 87 | static int mmc_schedule_delayed_work(struct delayed_work *work, | 71 | static int mmc_schedule_delayed_work(struct delayed_work *work, |
| @@ -302,7 +286,8 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception) | |||
| 302 | } | 286 | } |
| 303 | 287 | ||
| 304 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 288 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 305 | EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal, true); | 289 | EXT_CSD_BKOPS_START, 1, timeout, |
| 290 | use_busy_signal, true, false); | ||
| 306 | if (err) { | 291 | if (err) { |
| 307 | pr_warn("%s: Error %d starting bkops\n", | 292 | pr_warn("%s: Error %d starting bkops\n", |
| 308 | mmc_hostname(card->host), err); | 293 | mmc_hostname(card->host), err); |
| @@ -1950,7 +1935,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, | |||
| 1950 | cmd.opcode = MMC_ERASE; | 1935 | cmd.opcode = MMC_ERASE; |
| 1951 | cmd.arg = arg; | 1936 | cmd.arg = arg; |
| 1952 | cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | 1937 | cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; |
| 1953 | cmd.cmd_timeout_ms = mmc_erase_timeout(card, arg, qty); | 1938 | cmd.busy_timeout = mmc_erase_timeout(card, arg, qty); |
| 1954 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | 1939 | err = mmc_wait_for_cmd(card->host, &cmd, 0); |
| 1955 | if (err) { | 1940 | if (err) { |
| 1956 | pr_err("mmc_erase: erase error %d, status %#x\n", | 1941 | pr_err("mmc_erase: erase error %d, status %#x\n", |
| @@ -2137,7 +2122,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, | |||
| 2137 | y = 0; | 2122 | y = 0; |
| 2138 | for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) { | 2123 | for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) { |
| 2139 | timeout = mmc_erase_timeout(card, arg, qty + x); | 2124 | timeout = mmc_erase_timeout(card, arg, qty + x); |
| 2140 | if (timeout > host->max_discard_to) | 2125 | if (timeout > host->max_busy_timeout) |
| 2141 | break; | 2126 | break; |
| 2142 | if (timeout < last_timeout) | 2127 | if (timeout < last_timeout) |
| 2143 | break; | 2128 | break; |
| @@ -2169,7 +2154,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) | |||
| 2169 | struct mmc_host *host = card->host; | 2154 | struct mmc_host *host = card->host; |
| 2170 | unsigned int max_discard, max_trim; | 2155 | unsigned int max_discard, max_trim; |
| 2171 | 2156 | ||
| 2172 | if (!host->max_discard_to) | 2157 | if (!host->max_busy_timeout) |
| 2173 | return UINT_MAX; | 2158 | return UINT_MAX; |
| 2174 | 2159 | ||
| 2175 | /* | 2160 | /* |
| @@ -2189,7 +2174,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) | |||
| 2189 | max_discard = 0; | 2174 | max_discard = 0; |
| 2190 | } | 2175 | } |
| 2191 | pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n", | 2176 | pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n", |
| 2192 | mmc_hostname(host), max_discard, host->max_discard_to); | 2177 | mmc_hostname(host), max_discard, host->max_busy_timeout); |
| 2193 | return max_discard; | 2178 | return max_discard; |
| 2194 | } | 2179 | } |
| 2195 | EXPORT_SYMBOL(mmc_calc_max_discard); | 2180 | EXPORT_SYMBOL(mmc_calc_max_discard); |
| @@ -2248,9 +2233,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check) | |||
| 2248 | { | 2233 | { |
| 2249 | struct mmc_card *card = host->card; | 2234 | struct mmc_card *card = host->card; |
| 2250 | 2235 | ||
| 2251 | if (!host->bus_ops->power_restore) | ||
| 2252 | return -EOPNOTSUPP; | ||
| 2253 | |||
| 2254 | if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) | 2236 | if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) |
| 2255 | return -EOPNOTSUPP; | 2237 | return -EOPNOTSUPP; |
| 2256 | 2238 | ||
| @@ -2352,7 +2334,7 @@ int _mmc_detect_card_removed(struct mmc_host *host) | |||
| 2352 | { | 2334 | { |
| 2353 | int ret; | 2335 | int ret; |
| 2354 | 2336 | ||
| 2355 | if ((host->caps & MMC_CAP_NONREMOVABLE) || !host->bus_ops->alive) | 2337 | if (host->caps & MMC_CAP_NONREMOVABLE) |
| 2356 | return 0; | 2338 | return 0; |
| 2357 | 2339 | ||
| 2358 | if (!host->card || mmc_card_removed(host->card)) | 2340 | if (!host->card || mmc_card_removed(host->card)) |
| @@ -2435,7 +2417,7 @@ void mmc_rescan(struct work_struct *work) | |||
| 2435 | * if there is a _removable_ card registered, check whether it is | 2417 | * if there is a _removable_ card registered, check whether it is |
| 2436 | * still present | 2418 | * still present |
| 2437 | */ | 2419 | */ |
| 2438 | if (host->bus_ops && host->bus_ops->detect && !host->bus_dead | 2420 | if (host->bus_ops && !host->bus_dead |
| 2439 | && !(host->caps & MMC_CAP_NONREMOVABLE)) | 2421 | && !(host->caps & MMC_CAP_NONREMOVABLE)) |
| 2440 | host->bus_ops->detect(host); | 2422 | host->bus_ops->detect(host); |
| 2441 | 2423 | ||
| @@ -2490,6 +2472,7 @@ void mmc_start_host(struct mmc_host *host) | |||
| 2490 | mmc_power_off(host); | 2472 | mmc_power_off(host); |
| 2491 | else | 2473 | else |
| 2492 | mmc_power_up(host, host->ocr_avail); | 2474 | mmc_power_up(host, host->ocr_avail); |
| 2475 | mmc_gpiod_request_cd_irq(host); | ||
| 2493 | _mmc_detect_change(host, 0, false); | 2476 | _mmc_detect_change(host, 0, false); |
| 2494 | } | 2477 | } |
| 2495 | 2478 | ||
| @@ -2501,6 +2484,8 @@ void mmc_stop_host(struct mmc_host *host) | |||
| 2501 | host->removed = 1; | 2484 | host->removed = 1; |
| 2502 | spin_unlock_irqrestore(&host->lock, flags); | 2485 | spin_unlock_irqrestore(&host->lock, flags); |
| 2503 | #endif | 2486 | #endif |
| 2487 | if (host->slot.cd_irq >= 0) | ||
| 2488 | disable_irq(host->slot.cd_irq); | ||
| 2504 | 2489 | ||
| 2505 | host->rescan_disable = 1; | 2490 | host->rescan_disable = 1; |
| 2506 | cancel_delayed_work_sync(&host->detect); | 2491 | cancel_delayed_work_sync(&host->detect); |
| @@ -2537,7 +2522,7 @@ int mmc_power_save_host(struct mmc_host *host) | |||
| 2537 | 2522 | ||
| 2538 | mmc_bus_get(host); | 2523 | mmc_bus_get(host); |
| 2539 | 2524 | ||
| 2540 | if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { | 2525 | if (!host->bus_ops || host->bus_dead) { |
| 2541 | mmc_bus_put(host); | 2526 | mmc_bus_put(host); |
| 2542 | return -EINVAL; | 2527 | return -EINVAL; |
| 2543 | } | 2528 | } |
| @@ -2563,7 +2548,7 @@ int mmc_power_restore_host(struct mmc_host *host) | |||
| 2563 | 2548 | ||
| 2564 | mmc_bus_get(host); | 2549 | mmc_bus_get(host); |
| 2565 | 2550 | ||
| 2566 | if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { | 2551 | if (!host->bus_ops || host->bus_dead) { |
| 2567 | mmc_bus_put(host); | 2552 | mmc_bus_put(host); |
| 2568 | return -EINVAL; | 2553 | return -EINVAL; |
| 2569 | } | 2554 | } |
| @@ -2582,12 +2567,8 @@ EXPORT_SYMBOL(mmc_power_restore_host); | |||
| 2582 | */ | 2567 | */ |
| 2583 | int mmc_flush_cache(struct mmc_card *card) | 2568 | int mmc_flush_cache(struct mmc_card *card) |
| 2584 | { | 2569 | { |
| 2585 | struct mmc_host *host = card->host; | ||
| 2586 | int err = 0; | 2570 | int err = 0; |
| 2587 | 2571 | ||
| 2588 | if (!(host->caps2 & MMC_CAP2_CACHE_CTRL)) | ||
| 2589 | return err; | ||
| 2590 | |||
| 2591 | if (mmc_card_mmc(card) && | 2572 | if (mmc_card_mmc(card) && |
| 2592 | (card->ext_csd.cache_size > 0) && | 2573 | (card->ext_csd.cache_size > 0) && |
| 2593 | (card->ext_csd.cache_ctrl & 1)) { | 2574 | (card->ext_csd.cache_ctrl & 1)) { |
| @@ -2602,44 +2583,6 @@ int mmc_flush_cache(struct mmc_card *card) | |||
| 2602 | } | 2583 | } |
| 2603 | EXPORT_SYMBOL(mmc_flush_cache); | 2584 | EXPORT_SYMBOL(mmc_flush_cache); |
| 2604 | 2585 | ||
| 2605 | /* | ||
| 2606 | * Turn the cache ON/OFF. | ||
| 2607 | * Turning the cache OFF shall trigger flushing of the data | ||
| 2608 | * to the non-volatile storage. | ||
| 2609 | * This function should be called with host claimed | ||
| 2610 | */ | ||
| 2611 | int mmc_cache_ctrl(struct mmc_host *host, u8 enable) | ||
| 2612 | { | ||
| 2613 | struct mmc_card *card = host->card; | ||
| 2614 | unsigned int timeout; | ||
| 2615 | int err = 0; | ||
| 2616 | |||
| 2617 | if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) || | ||
| 2618 | mmc_card_is_removable(host)) | ||
| 2619 | return err; | ||
| 2620 | |||
| 2621 | if (card && mmc_card_mmc(card) && | ||
| 2622 | (card->ext_csd.cache_size > 0)) { | ||
| 2623 | enable = !!enable; | ||
| 2624 | |||
| 2625 | if (card->ext_csd.cache_ctrl ^ enable) { | ||
| 2626 | timeout = enable ? card->ext_csd.generic_cmd6_time : 0; | ||
| 2627 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
| 2628 | EXT_CSD_CACHE_CTRL, enable, timeout); | ||
| 2629 | if (err) | ||
| 2630 | pr_err("%s: cache %s error %d\n", | ||
| 2631 | mmc_hostname(card->host), | ||
| 2632 | enable ? "on" : "off", | ||
| 2633 | err); | ||
| 2634 | else | ||
| 2635 | card->ext_csd.cache_ctrl = enable; | ||
| 2636 | } | ||
| 2637 | } | ||
| 2638 | |||
| 2639 | return err; | ||
| 2640 | } | ||
| 2641 | EXPORT_SYMBOL(mmc_cache_ctrl); | ||
| 2642 | |||
| 2643 | #ifdef CONFIG_PM | 2586 | #ifdef CONFIG_PM |
| 2644 | 2587 | ||
| 2645 | /* Do the card removal on suspend if card is assumed removeable | 2588 | /* Do the card removal on suspend if card is assumed removeable |
| @@ -2668,7 +2611,7 @@ int mmc_pm_notify(struct notifier_block *notify_block, | |||
| 2668 | /* Validate prerequisites for suspend */ | 2611 | /* Validate prerequisites for suspend */ |
| 2669 | if (host->bus_ops->pre_suspend) | 2612 | if (host->bus_ops->pre_suspend) |
| 2670 | err = host->bus_ops->pre_suspend(host); | 2613 | err = host->bus_ops->pre_suspend(host); |
| 2671 | if (!err && host->bus_ops->suspend) | 2614 | if (!err) |
| 2672 | break; | 2615 | break; |
| 2673 | 2616 | ||
| 2674 | /* Calling bus_ops->remove() with a claimed host can deadlock */ | 2617 | /* Calling bus_ops->remove() with a claimed host can deadlock */ |
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 114f6bdfbef3..fdea825dbb24 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
| @@ -419,6 +419,16 @@ int mmc_of_parse(struct mmc_host *host) | |||
| 419 | host->caps |= MMC_CAP_SD_HIGHSPEED; | 419 | host->caps |= MMC_CAP_SD_HIGHSPEED; |
| 420 | if (of_find_property(np, "cap-mmc-highspeed", &len)) | 420 | if (of_find_property(np, "cap-mmc-highspeed", &len)) |
| 421 | host->caps |= MMC_CAP_MMC_HIGHSPEED; | 421 | host->caps |= MMC_CAP_MMC_HIGHSPEED; |
| 422 | if (of_find_property(np, "sd-uhs-sdr12", &len)) | ||
| 423 | host->caps |= MMC_CAP_UHS_SDR12; | ||
| 424 | if (of_find_property(np, "sd-uhs-sdr25", &len)) | ||
| 425 | host->caps |= MMC_CAP_UHS_SDR25; | ||
| 426 | if (of_find_property(np, "sd-uhs-sdr50", &len)) | ||
| 427 | host->caps |= MMC_CAP_UHS_SDR50; | ||
| 428 | if (of_find_property(np, "sd-uhs-sdr104", &len)) | ||
| 429 | host->caps |= MMC_CAP_UHS_SDR104; | ||
| 430 | if (of_find_property(np, "sd-uhs-ddr50", &len)) | ||
| 431 | host->caps |= MMC_CAP_UHS_DDR50; | ||
| 422 | if (of_find_property(np, "cap-power-off-card", &len)) | 432 | if (of_find_property(np, "cap-power-off-card", &len)) |
| 423 | host->caps |= MMC_CAP_POWER_OFF_CARD; | 433 | host->caps |= MMC_CAP_POWER_OFF_CARD; |
| 424 | if (of_find_property(np, "cap-sdio-irq", &len)) | 434 | if (of_find_property(np, "cap-sdio-irq", &len)) |
| @@ -429,6 +439,14 @@ int mmc_of_parse(struct mmc_host *host) | |||
| 429 | host->pm_caps |= MMC_PM_KEEP_POWER; | 439 | host->pm_caps |= MMC_PM_KEEP_POWER; |
| 430 | if (of_find_property(np, "enable-sdio-wakeup", &len)) | 440 | if (of_find_property(np, "enable-sdio-wakeup", &len)) |
| 431 | host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; | 441 | host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; |
| 442 | if (of_find_property(np, "mmc-ddr-1_8v", &len)) | ||
| 443 | host->caps |= MMC_CAP_1_8V_DDR; | ||
| 444 | if (of_find_property(np, "mmc-ddr-1_2v", &len)) | ||
| 445 | host->caps |= MMC_CAP_1_2V_DDR; | ||
| 446 | if (of_find_property(np, "mmc-hs200-1_8v", &len)) | ||
| 447 | host->caps2 |= MMC_CAP2_HS200_1_8V_SDR; | ||
| 448 | if (of_find_property(np, "mmc-hs200-1_2v", &len)) | ||
| 449 | host->caps2 |= MMC_CAP2_HS200_1_2V_SDR; | ||
| 432 | 450 | ||
| 433 | return 0; | 451 | return 0; |
| 434 | 452 | ||
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 98e9eb0f6643..1ab5f3a0af5b 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
| @@ -856,8 +856,10 @@ static int mmc_select_hs200(struct mmc_card *card) | |||
| 856 | 856 | ||
| 857 | /* switch to HS200 mode if bus width set successfully */ | 857 | /* switch to HS200 mode if bus width set successfully */ |
| 858 | if (!err) | 858 | if (!err) |
| 859 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 859 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 860 | EXT_CSD_HS_TIMING, 2, 0); | 860 | EXT_CSD_HS_TIMING, 2, |
| 861 | card->ext_csd.generic_cmd6_time, | ||
| 862 | true, true, true); | ||
| 861 | err: | 863 | err: |
| 862 | return err; | 864 | return err; |
| 863 | } | 865 | } |
| @@ -1074,9 +1076,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 1074 | host->caps2 & MMC_CAP2_HS200) | 1076 | host->caps2 & MMC_CAP2_HS200) |
| 1075 | err = mmc_select_hs200(card); | 1077 | err = mmc_select_hs200(card); |
| 1076 | else if (host->caps & MMC_CAP_MMC_HIGHSPEED) | 1078 | else if (host->caps & MMC_CAP_MMC_HIGHSPEED) |
| 1077 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1079 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 1078 | EXT_CSD_HS_TIMING, 1, | 1080 | EXT_CSD_HS_TIMING, 1, |
| 1079 | card->ext_csd.generic_cmd6_time); | 1081 | card->ext_csd.generic_cmd6_time, |
| 1082 | true, true, true); | ||
| 1080 | 1083 | ||
| 1081 | if (err && err != -EBADMSG) | 1084 | if (err && err != -EBADMSG) |
| 1082 | goto free_card; | 1085 | goto free_card; |
| @@ -1287,8 +1290,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 1287 | * If cache size is higher than 0, this indicates | 1290 | * If cache size is higher than 0, this indicates |
| 1288 | * the existence of cache and it can be turned on. | 1291 | * the existence of cache and it can be turned on. |
| 1289 | */ | 1292 | */ |
| 1290 | if ((host->caps2 & MMC_CAP2_CACHE_CTRL) && | 1293 | if (card->ext_csd.cache_size > 0) { |
| 1291 | card->ext_csd.cache_size > 0) { | ||
| 1292 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1294 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 1293 | EXT_CSD_CACHE_CTRL, 1, | 1295 | EXT_CSD_CACHE_CTRL, 1, |
| 1294 | card->ext_csd.generic_cmd6_time); | 1296 | card->ext_csd.generic_cmd6_time); |
| @@ -1356,11 +1358,9 @@ static int mmc_sleep(struct mmc_host *host) | |||
| 1356 | { | 1358 | { |
| 1357 | struct mmc_command cmd = {0}; | 1359 | struct mmc_command cmd = {0}; |
| 1358 | struct mmc_card *card = host->card; | 1360 | struct mmc_card *card = host->card; |
| 1361 | unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000); | ||
| 1359 | int err; | 1362 | int err; |
| 1360 | 1363 | ||
| 1361 | if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD) | ||
| 1362 | return 0; | ||
| 1363 | |||
| 1364 | err = mmc_deselect_cards(host); | 1364 | err = mmc_deselect_cards(host); |
| 1365 | if (err) | 1365 | if (err) |
| 1366 | return err; | 1366 | return err; |
| @@ -1369,7 +1369,19 @@ static int mmc_sleep(struct mmc_host *host) | |||
| 1369 | cmd.arg = card->rca << 16; | 1369 | cmd.arg = card->rca << 16; |
| 1370 | cmd.arg |= 1 << 15; | 1370 | cmd.arg |= 1 << 15; |
| 1371 | 1371 | ||
| 1372 | cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; | 1372 | /* |
| 1373 | * If the max_busy_timeout of the host is specified, validate it against | ||
| 1374 | * the sleep cmd timeout. A failure means we need to prevent the host | ||
| 1375 | * from doing hw busy detection, which is done by converting to a R1 | ||
| 1376 | * response instead of a R1B. | ||
| 1377 | */ | ||
| 1378 | if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) { | ||
| 1379 | cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; | ||
| 1380 | } else { | ||
| 1381 | cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; | ||
| 1382 | cmd.busy_timeout = timeout_ms; | ||
| 1383 | } | ||
| 1384 | |||
| 1373 | err = mmc_wait_for_cmd(host, &cmd, 0); | 1385 | err = mmc_wait_for_cmd(host, &cmd, 0); |
| 1374 | if (err) | 1386 | if (err) |
| 1375 | return err; | 1387 | return err; |
| @@ -1380,8 +1392,8 @@ static int mmc_sleep(struct mmc_host *host) | |||
| 1380 | * SEND_STATUS command to poll the status because that command (and most | 1392 | * SEND_STATUS command to poll the status because that command (and most |
| 1381 | * others) is invalid while the card sleeps. | 1393 | * others) is invalid while the card sleeps. |
| 1382 | */ | 1394 | */ |
| 1383 | if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) | 1395 | if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) |
| 1384 | mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); | 1396 | mmc_delay(timeout_ms); |
| 1385 | 1397 | ||
| 1386 | return err; | 1398 | return err; |
| 1387 | } | 1399 | } |
| @@ -1404,7 +1416,7 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) | |||
| 1404 | 1416 | ||
| 1405 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1417 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 1406 | EXT_CSD_POWER_OFF_NOTIFICATION, | 1418 | EXT_CSD_POWER_OFF_NOTIFICATION, |
| 1407 | notify_type, timeout, true, false); | 1419 | notify_type, timeout, true, false, false); |
| 1408 | if (err) | 1420 | if (err) |
| 1409 | pr_err("%s: Power Off Notification timed out, %u\n", | 1421 | pr_err("%s: Power Off Notification timed out, %u\n", |
| 1410 | mmc_hostname(card->host), timeout); | 1422 | mmc_hostname(card->host), timeout); |
| @@ -1484,7 +1496,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) | |||
| 1484 | goto out; | 1496 | goto out; |
| 1485 | } | 1497 | } |
| 1486 | 1498 | ||
| 1487 | err = mmc_cache_ctrl(host, 0); | 1499 | err = mmc_flush_cache(host->card); |
| 1488 | if (err) | 1500 | if (err) |
| 1489 | goto out; | 1501 | goto out; |
| 1490 | 1502 | ||
| @@ -1636,16 +1648,6 @@ static int mmc_power_restore(struct mmc_host *host) | |||
| 1636 | static const struct mmc_bus_ops mmc_ops = { | 1648 | static const struct mmc_bus_ops mmc_ops = { |
| 1637 | .remove = mmc_remove, | 1649 | .remove = mmc_remove, |
| 1638 | .detect = mmc_detect, | 1650 | .detect = mmc_detect, |
| 1639 | .suspend = NULL, | ||
| 1640 | .resume = NULL, | ||
| 1641 | .power_restore = mmc_power_restore, | ||
| 1642 | .alive = mmc_alive, | ||
| 1643 | .shutdown = mmc_shutdown, | ||
| 1644 | }; | ||
| 1645 | |||
| 1646 | static const struct mmc_bus_ops mmc_ops_unsafe = { | ||
| 1647 | .remove = mmc_remove, | ||
| 1648 | .detect = mmc_detect, | ||
| 1649 | .suspend = mmc_suspend, | 1651 | .suspend = mmc_suspend, |
| 1650 | .resume = mmc_resume, | 1652 | .resume = mmc_resume, |
| 1651 | .runtime_suspend = mmc_runtime_suspend, | 1653 | .runtime_suspend = mmc_runtime_suspend, |
| @@ -1655,17 +1657,6 @@ static const struct mmc_bus_ops mmc_ops_unsafe = { | |||
| 1655 | .shutdown = mmc_shutdown, | 1657 | .shutdown = mmc_shutdown, |
| 1656 | }; | 1658 | }; |
| 1657 | 1659 | ||
| 1658 | static void mmc_attach_bus_ops(struct mmc_host *host) | ||
| 1659 | { | ||
| 1660 | const struct mmc_bus_ops *bus_ops; | ||
| 1661 | |||
| 1662 | if (!mmc_card_is_removable(host)) | ||
| 1663 | bus_ops = &mmc_ops_unsafe; | ||
| 1664 | else | ||
| 1665 | bus_ops = &mmc_ops; | ||
| 1666 | mmc_attach_bus(host, bus_ops); | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | /* | 1660 | /* |
| 1670 | * Starting point for MMC card init. | 1661 | * Starting point for MMC card init. |
| 1671 | */ | 1662 | */ |
| @@ -1685,7 +1676,7 @@ int mmc_attach_mmc(struct mmc_host *host) | |||
| 1685 | if (err) | 1676 | if (err) |
| 1686 | return err; | 1677 | return err; |
| 1687 | 1678 | ||
| 1688 | mmc_attach_bus_ops(host); | 1679 | mmc_attach_bus(host, &mmc_ops); |
| 1689 | if (host->ocr_avail_mmc) | 1680 | if (host->ocr_avail_mmc) |
| 1690 | host->ocr_avail = host->ocr_avail_mmc; | 1681 | host->ocr_avail = host->ocr_avail_mmc; |
| 1691 | 1682 | ||
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index e5b5eeb548d1..f51b5ba3bbea 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c | |||
| @@ -405,20 +405,30 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc) | |||
| 405 | * timeout of zero implies maximum possible timeout | 405 | * timeout of zero implies maximum possible timeout |
| 406 | * @use_busy_signal: use the busy signal as response type | 406 | * @use_busy_signal: use the busy signal as response type |
| 407 | * @send_status: send status cmd to poll for busy | 407 | * @send_status: send status cmd to poll for busy |
| 408 | * @ignore_crc: ignore CRC errors when sending status cmd to poll for busy | ||
| 408 | * | 409 | * |
| 409 | * Modifies the EXT_CSD register for selected card. | 410 | * Modifies the EXT_CSD register for selected card. |
| 410 | */ | 411 | */ |
| 411 | int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | 412 | int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, |
| 412 | unsigned int timeout_ms, bool use_busy_signal, bool send_status) | 413 | unsigned int timeout_ms, bool use_busy_signal, bool send_status, |
| 414 | bool ignore_crc) | ||
| 413 | { | 415 | { |
| 416 | struct mmc_host *host = card->host; | ||
| 414 | int err; | 417 | int err; |
| 415 | struct mmc_command cmd = {0}; | 418 | struct mmc_command cmd = {0}; |
| 416 | unsigned long timeout; | 419 | unsigned long timeout; |
| 417 | u32 status = 0; | 420 | u32 status = 0; |
| 418 | bool ignore_crc = false; | 421 | bool use_r1b_resp = use_busy_signal; |
| 419 | 422 | ||
| 420 | BUG_ON(!card); | 423 | /* |
| 421 | BUG_ON(!card->host); | 424 | * If the cmd timeout and the max_busy_timeout of the host are both |
| 425 | * specified, let's validate them. A failure means we need to prevent | ||
| 426 | * the host from doing hw busy detection, which is done by converting | ||
| 427 | * to a R1 response instead of a R1B. | ||
| 428 | */ | ||
| 429 | if (timeout_ms && host->max_busy_timeout && | ||
| 430 | (timeout_ms > host->max_busy_timeout)) | ||
| 431 | use_r1b_resp = false; | ||
| 422 | 432 | ||
| 423 | cmd.opcode = MMC_SWITCH; | 433 | cmd.opcode = MMC_SWITCH; |
| 424 | cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | | 434 | cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | |
| @@ -426,17 +436,21 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | |||
| 426 | (value << 8) | | 436 | (value << 8) | |
| 427 | set; | 437 | set; |
| 428 | cmd.flags = MMC_CMD_AC; | 438 | cmd.flags = MMC_CMD_AC; |
| 429 | if (use_busy_signal) | 439 | if (use_r1b_resp) { |
| 430 | cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; | 440 | cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; |
| 431 | else | 441 | /* |
| 442 | * A busy_timeout of zero means the host can decide to use | ||
| 443 | * whatever value it finds suitable. | ||
| 444 | */ | ||
| 445 | cmd.busy_timeout = timeout_ms; | ||
| 446 | } else { | ||
| 432 | cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; | 447 | cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; |
| 448 | } | ||
| 433 | 449 | ||
| 434 | |||
| 435 | cmd.cmd_timeout_ms = timeout_ms; | ||
| 436 | if (index == EXT_CSD_SANITIZE_START) | 450 | if (index == EXT_CSD_SANITIZE_START) |
| 437 | cmd.sanitize_busy = true; | 451 | cmd.sanitize_busy = true; |
| 438 | 452 | ||
| 439 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); | 453 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); |
| 440 | if (err) | 454 | if (err) |
| 441 | return err; | 455 | return err; |
| 442 | 456 | ||
| @@ -445,24 +459,27 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | |||
| 445 | return 0; | 459 | return 0; |
| 446 | 460 | ||
| 447 | /* | 461 | /* |
| 448 | * Must check status to be sure of no errors | 462 | * CRC errors shall only be ignored in cases were CMD13 is used to poll |
| 449 | * If CMD13 is to check the busy completion of the timing change, | 463 | * to detect busy completion. |
| 450 | * disable the check of CRC error. | ||
| 451 | */ | 464 | */ |
| 452 | if (index == EXT_CSD_HS_TIMING && | 465 | if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) |
| 453 | !(card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)) | 466 | ignore_crc = false; |
| 454 | ignore_crc = true; | 467 | |
| 468 | /* We have an unspecified cmd timeout, use the fallback value. */ | ||
| 469 | if (!timeout_ms) | ||
| 470 | timeout_ms = MMC_OPS_TIMEOUT_MS; | ||
| 455 | 471 | ||
| 456 | timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS); | 472 | /* Must check status to be sure of no errors. */ |
| 473 | timeout = jiffies + msecs_to_jiffies(timeout_ms); | ||
| 457 | do { | 474 | do { |
| 458 | if (send_status) { | 475 | if (send_status) { |
| 459 | err = __mmc_send_status(card, &status, ignore_crc); | 476 | err = __mmc_send_status(card, &status, ignore_crc); |
| 460 | if (err) | 477 | if (err) |
| 461 | return err; | 478 | return err; |
| 462 | } | 479 | } |
| 463 | if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) | 480 | if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) |
| 464 | break; | 481 | break; |
| 465 | if (mmc_host_is_spi(card->host)) | 482 | if (mmc_host_is_spi(host)) |
| 466 | break; | 483 | break; |
| 467 | 484 | ||
| 468 | /* | 485 | /* |
| @@ -478,18 +495,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | |||
| 478 | /* Timeout if the device never leaves the program state. */ | 495 | /* Timeout if the device never leaves the program state. */ |
| 479 | if (time_after(jiffies, timeout)) { | 496 | if (time_after(jiffies, timeout)) { |
| 480 | pr_err("%s: Card stuck in programming state! %s\n", | 497 | pr_err("%s: Card stuck in programming state! %s\n", |
| 481 | mmc_hostname(card->host), __func__); | 498 | mmc_hostname(host), __func__); |
| 482 | return -ETIMEDOUT; | 499 | return -ETIMEDOUT; |
| 483 | } | 500 | } |
| 484 | } while (R1_CURRENT_STATE(status) == R1_STATE_PRG); | 501 | } while (R1_CURRENT_STATE(status) == R1_STATE_PRG); |
| 485 | 502 | ||
| 486 | if (mmc_host_is_spi(card->host)) { | 503 | if (mmc_host_is_spi(host)) { |
| 487 | if (status & R1_SPI_ILLEGAL_COMMAND) | 504 | if (status & R1_SPI_ILLEGAL_COMMAND) |
| 488 | return -EBADMSG; | 505 | return -EBADMSG; |
| 489 | } else { | 506 | } else { |
| 490 | if (status & 0xFDFFA000) | 507 | if (status & 0xFDFFA000) |
| 491 | pr_warning("%s: unexpected status %#x after " | 508 | pr_warn("%s: unexpected status %#x after switch\n", |
| 492 | "switch", mmc_hostname(card->host), status); | 509 | mmc_hostname(host), status); |
| 493 | if (status & R1_SWITCH_ERROR) | 510 | if (status & R1_SWITCH_ERROR) |
| 494 | return -EBADMSG; | 511 | return -EBADMSG; |
| 495 | } | 512 | } |
| @@ -501,7 +518,8 @@ EXPORT_SYMBOL_GPL(__mmc_switch); | |||
| 501 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | 518 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, |
| 502 | unsigned int timeout_ms) | 519 | unsigned int timeout_ms) |
| 503 | { | 520 | { |
| 504 | return __mmc_switch(card, set, index, value, timeout_ms, true, true); | 521 | return __mmc_switch(card, set, index, value, timeout_ms, true, true, |
| 522 | false); | ||
| 505 | } | 523 | } |
| 506 | EXPORT_SYMBOL_GPL(mmc_switch); | 524 | EXPORT_SYMBOL_GPL(mmc_switch); |
| 507 | 525 | ||
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 692fdb177294..2dd359d2242f 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
| @@ -1209,16 +1209,6 @@ static int mmc_sd_power_restore(struct mmc_host *host) | |||
| 1209 | static const struct mmc_bus_ops mmc_sd_ops = { | 1209 | static const struct mmc_bus_ops mmc_sd_ops = { |
| 1210 | .remove = mmc_sd_remove, | 1210 | .remove = mmc_sd_remove, |
| 1211 | .detect = mmc_sd_detect, | 1211 | .detect = mmc_sd_detect, |
| 1212 | .suspend = NULL, | ||
| 1213 | .resume = NULL, | ||
| 1214 | .power_restore = mmc_sd_power_restore, | ||
| 1215 | .alive = mmc_sd_alive, | ||
| 1216 | .shutdown = mmc_sd_suspend, | ||
| 1217 | }; | ||
| 1218 | |||
| 1219 | static const struct mmc_bus_ops mmc_sd_ops_unsafe = { | ||
| 1220 | .remove = mmc_sd_remove, | ||
| 1221 | .detect = mmc_sd_detect, | ||
| 1222 | .runtime_suspend = mmc_sd_runtime_suspend, | 1212 | .runtime_suspend = mmc_sd_runtime_suspend, |
| 1223 | .runtime_resume = mmc_sd_runtime_resume, | 1213 | .runtime_resume = mmc_sd_runtime_resume, |
| 1224 | .suspend = mmc_sd_suspend, | 1214 | .suspend = mmc_sd_suspend, |
| @@ -1228,17 +1218,6 @@ static const struct mmc_bus_ops mmc_sd_ops_unsafe = { | |||
| 1228 | .shutdown = mmc_sd_suspend, | 1218 | .shutdown = mmc_sd_suspend, |
| 1229 | }; | 1219 | }; |
| 1230 | 1220 | ||
| 1231 | static void mmc_sd_attach_bus_ops(struct mmc_host *host) | ||
| 1232 | { | ||
| 1233 | const struct mmc_bus_ops *bus_ops; | ||
| 1234 | |||
| 1235 | if (!mmc_card_is_removable(host)) | ||
| 1236 | bus_ops = &mmc_sd_ops_unsafe; | ||
| 1237 | else | ||
| 1238 | bus_ops = &mmc_sd_ops; | ||
| 1239 | mmc_attach_bus(host, bus_ops); | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | /* | 1221 | /* |
| 1243 | * Starting point for SD card init. | 1222 | * Starting point for SD card init. |
| 1244 | */ | 1223 | */ |
| @@ -1254,7 +1233,7 @@ int mmc_attach_sd(struct mmc_host *host) | |||
| 1254 | if (err) | 1233 | if (err) |
| 1255 | return err; | 1234 | return err; |
| 1256 | 1235 | ||
| 1257 | mmc_sd_attach_bus_ops(host); | 1236 | mmc_attach_bus(host, &mmc_sd_ops); |
| 1258 | if (host->ocr_avail_sd) | 1237 | if (host->ocr_avail_sd) |
| 1259 | host->ocr_avail = host->ocr_avail_sd; | 1238 | host->ocr_avail = host->ocr_avail_sd; |
| 1260 | 1239 | ||
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 46596b71a32f..f7650b899e3d 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include <linux/err.h> | 11 | #include <linux/err.h> |
| 12 | #include <linux/gpio.h> | 12 | #include <linux/gpio.h> |
| 13 | #include <linux/gpio/consumer.h> | ||
| 13 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
| 14 | #include <linux/jiffies.h> | 15 | #include <linux/jiffies.h> |
| 15 | #include <linux/mmc/host.h> | 16 | #include <linux/mmc/host.h> |
| @@ -18,8 +19,10 @@ | |||
| 18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 19 | 20 | ||
| 20 | struct mmc_gpio { | 21 | struct mmc_gpio { |
| 21 | int ro_gpio; | 22 | struct gpio_desc *ro_gpio; |
| 22 | int cd_gpio; | 23 | struct gpio_desc *cd_gpio; |
| 24 | bool override_ro_active_level; | ||
| 25 | bool override_cd_active_level; | ||
| 23 | char *ro_label; | 26 | char *ro_label; |
| 24 | char cd_label[0]; | 27 | char cd_label[0]; |
| 25 | }; | 28 | }; |
| @@ -57,8 +60,6 @@ static int mmc_gpio_alloc(struct mmc_host *host) | |||
| 57 | ctx->ro_label = ctx->cd_label + len; | 60 | ctx->ro_label = ctx->cd_label + len; |
| 58 | snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); | 61 | snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); |
| 59 | snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent)); | 62 | snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent)); |
| 60 | ctx->cd_gpio = -EINVAL; | ||
| 61 | ctx->ro_gpio = -EINVAL; | ||
| 62 | host->slot.handler_priv = ctx; | 63 | host->slot.handler_priv = ctx; |
| 63 | } | 64 | } |
| 64 | } | 65 | } |
| @@ -72,11 +73,14 @@ int mmc_gpio_get_ro(struct mmc_host *host) | |||
| 72 | { | 73 | { |
| 73 | struct mmc_gpio *ctx = host->slot.handler_priv; | 74 | struct mmc_gpio *ctx = host->slot.handler_priv; |
| 74 | 75 | ||
| 75 | if (!ctx || !gpio_is_valid(ctx->ro_gpio)) | 76 | if (!ctx || !ctx->ro_gpio) |
| 76 | return -ENOSYS; | 77 | return -ENOSYS; |
| 77 | 78 | ||
| 78 | return !gpio_get_value_cansleep(ctx->ro_gpio) ^ | 79 | if (ctx->override_ro_active_level) |
| 79 | !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH); | 80 | return !gpiod_get_raw_value_cansleep(ctx->ro_gpio) ^ |
| 81 | !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH); | ||
| 82 | |||
| 83 | return gpiod_get_value_cansleep(ctx->ro_gpio); | ||
| 80 | } | 84 | } |
| 81 | EXPORT_SYMBOL(mmc_gpio_get_ro); | 85 | EXPORT_SYMBOL(mmc_gpio_get_ro); |
| 82 | 86 | ||
| @@ -84,11 +88,14 @@ int mmc_gpio_get_cd(struct mmc_host *host) | |||
| 84 | { | 88 | { |
| 85 | struct mmc_gpio *ctx = host->slot.handler_priv; | 89 | struct mmc_gpio *ctx = host->slot.handler_priv; |
| 86 | 90 | ||
| 87 | if (!ctx || !gpio_is_valid(ctx->cd_gpio)) | 91 | if (!ctx || !ctx->cd_gpio) |
| 88 | return -ENOSYS; | 92 | return -ENOSYS; |
| 89 | 93 | ||
| 90 | return !gpio_get_value_cansleep(ctx->cd_gpio) ^ | 94 | if (ctx->override_cd_active_level) |
| 91 | !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); | 95 | return !gpiod_get_raw_value_cansleep(ctx->cd_gpio) ^ |
| 96 | !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); | ||
| 97 | |||
| 98 | return gpiod_get_value_cansleep(ctx->cd_gpio); | ||
| 92 | } | 99 | } |
| 93 | EXPORT_SYMBOL(mmc_gpio_get_cd); | 100 | EXPORT_SYMBOL(mmc_gpio_get_cd); |
| 94 | 101 | ||
| @@ -125,12 +132,47 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) | |||
| 125 | if (ret < 0) | 132 | if (ret < 0) |
| 126 | return ret; | 133 | return ret; |
| 127 | 134 | ||
| 128 | ctx->ro_gpio = gpio; | 135 | ctx->override_ro_active_level = true; |
| 136 | ctx->ro_gpio = gpio_to_desc(gpio); | ||
| 129 | 137 | ||
| 130 | return 0; | 138 | return 0; |
| 131 | } | 139 | } |
| 132 | EXPORT_SYMBOL(mmc_gpio_request_ro); | 140 | EXPORT_SYMBOL(mmc_gpio_request_ro); |
| 133 | 141 | ||
| 142 | void mmc_gpiod_request_cd_irq(struct mmc_host *host) | ||
| 143 | { | ||
| 144 | struct mmc_gpio *ctx = host->slot.handler_priv; | ||
| 145 | int ret, irq; | ||
| 146 | |||
| 147 | if (host->slot.cd_irq >= 0 || !ctx || !ctx->cd_gpio) | ||
| 148 | return; | ||
| 149 | |||
| 150 | irq = gpiod_to_irq(ctx->cd_gpio); | ||
| 151 | |||
| 152 | /* | ||
| 153 | * Even if gpiod_to_irq() returns a valid IRQ number, the platform might | ||
| 154 | * still prefer to poll, e.g., because that IRQ number is already used | ||
| 155 | * by another unit and cannot be shared. | ||
| 156 | */ | ||
| 157 | if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL) | ||
| 158 | irq = -EINVAL; | ||
| 159 | |||
| 160 | if (irq >= 0) { | ||
| 161 | ret = devm_request_threaded_irq(&host->class_dev, irq, | ||
| 162 | NULL, mmc_gpio_cd_irqt, | ||
| 163 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 164 | ctx->cd_label, host); | ||
| 165 | if (ret < 0) | ||
| 166 | irq = ret; | ||
| 167 | } | ||
| 168 | |||
| 169 | host->slot.cd_irq = irq; | ||
| 170 | |||
| 171 | if (irq < 0) | ||
| 172 | host->caps |= MMC_CAP_NEEDS_POLL; | ||
| 173 | } | ||
| 174 | EXPORT_SYMBOL(mmc_gpiod_request_cd_irq); | ||
| 175 | |||
| 134 | /** | 176 | /** |
| 135 | * mmc_gpio_request_cd - request a gpio for card-detection | 177 | * mmc_gpio_request_cd - request a gpio for card-detection |
| 136 | * @host: mmc host | 178 | * @host: mmc host |
| @@ -154,7 +196,6 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, | |||
| 154 | unsigned int debounce) | 196 | unsigned int debounce) |
| 155 | { | 197 | { |
| 156 | struct mmc_gpio *ctx; | 198 | struct mmc_gpio *ctx; |
| 157 | int irq = gpio_to_irq(gpio); | ||
| 158 | int ret; | 199 | int ret; |
| 159 | 200 | ||
| 160 | ret = mmc_gpio_alloc(host); | 201 | ret = mmc_gpio_alloc(host); |
| @@ -179,29 +220,10 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, | |||
| 179 | return ret; | 220 | return ret; |
| 180 | } | 221 | } |
| 181 | 222 | ||
| 182 | /* | 223 | ctx->override_cd_active_level = true; |
| 183 | * Even if gpio_to_irq() returns a valid IRQ number, the platform might | 224 | ctx->cd_gpio = gpio_to_desc(gpio); |
| 184 | * still prefer to poll, e.g., because that IRQ number is already used | ||
| 185 | * by another unit and cannot be shared. | ||
| 186 | */ | ||
| 187 | if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL) | ||
| 188 | irq = -EINVAL; | ||
| 189 | |||
| 190 | if (irq >= 0) { | ||
| 191 | ret = devm_request_threaded_irq(&host->class_dev, irq, | ||
| 192 | NULL, mmc_gpio_cd_irqt, | ||
| 193 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 194 | ctx->cd_label, host); | ||
| 195 | if (ret < 0) | ||
| 196 | irq = ret; | ||
| 197 | } | ||
| 198 | |||
| 199 | host->slot.cd_irq = irq; | ||
| 200 | |||
| 201 | if (irq < 0) | ||
| 202 | host->caps |= MMC_CAP_NEEDS_POLL; | ||
| 203 | 225 | ||
| 204 | ctx->cd_gpio = gpio; | 226 | mmc_gpiod_request_cd_irq(host); |
| 205 | 227 | ||
| 206 | return 0; | 228 | return 0; |
| 207 | } | 229 | } |
| @@ -219,11 +241,11 @@ void mmc_gpio_free_ro(struct mmc_host *host) | |||
| 219 | struct mmc_gpio *ctx = host->slot.handler_priv; | 241 | struct mmc_gpio *ctx = host->slot.handler_priv; |
| 220 | int gpio; | 242 | int gpio; |
| 221 | 243 | ||
| 222 | if (!ctx || !gpio_is_valid(ctx->ro_gpio)) | 244 | if (!ctx || !ctx->ro_gpio) |
| 223 | return; | 245 | return; |
| 224 | 246 | ||
| 225 | gpio = ctx->ro_gpio; | 247 | gpio = desc_to_gpio(ctx->ro_gpio); |
| 226 | ctx->ro_gpio = -EINVAL; | 248 | ctx->ro_gpio = NULL; |
| 227 | 249 | ||
| 228 | devm_gpio_free(&host->class_dev, gpio); | 250 | devm_gpio_free(&host->class_dev, gpio); |
| 229 | } | 251 | } |
| @@ -241,7 +263,7 @@ void mmc_gpio_free_cd(struct mmc_host *host) | |||
| 241 | struct mmc_gpio *ctx = host->slot.handler_priv; | 263 | struct mmc_gpio *ctx = host->slot.handler_priv; |
| 242 | int gpio; | 264 | int gpio; |
| 243 | 265 | ||
| 244 | if (!ctx || !gpio_is_valid(ctx->cd_gpio)) | 266 | if (!ctx || !ctx->cd_gpio) |
| 245 | return; | 267 | return; |
| 246 | 268 | ||
| 247 | if (host->slot.cd_irq >= 0) { | 269 | if (host->slot.cd_irq >= 0) { |
| @@ -249,9 +271,87 @@ void mmc_gpio_free_cd(struct mmc_host *host) | |||
| 249 | host->slot.cd_irq = -EINVAL; | 271 | host->slot.cd_irq = -EINVAL; |
| 250 | } | 272 | } |
| 251 | 273 | ||
| 252 | gpio = ctx->cd_gpio; | 274 | gpio = desc_to_gpio(ctx->cd_gpio); |
| 253 | ctx->cd_gpio = -EINVAL; | 275 | ctx->cd_gpio = NULL; |
| 254 | 276 | ||
| 255 | devm_gpio_free(&host->class_dev, gpio); | 277 | devm_gpio_free(&host->class_dev, gpio); |
| 256 | } | 278 | } |
| 257 | EXPORT_SYMBOL(mmc_gpio_free_cd); | 279 | EXPORT_SYMBOL(mmc_gpio_free_cd); |
| 280 | |||
| 281 | /** | ||
| 282 | * mmc_gpiod_request_cd - request a gpio descriptor for card-detection | ||
| 283 | * @host: mmc host | ||
| 284 | * @con_id: function within the GPIO consumer | ||
| 285 | * @idx: index of the GPIO to obtain in the consumer | ||
| 286 | * @override_active_level: ignore %GPIO_ACTIVE_LOW flag | ||
| 287 | * @debounce: debounce time in microseconds | ||
| 288 | * | ||
| 289 | * Use this function in place of mmc_gpio_request_cd() to use the GPIO | ||
| 290 | * descriptor API. Note that it is paired with mmc_gpiod_free_cd() not | ||
| 291 | * mmc_gpio_free_cd(). Note also that it must be called prior to mmc_add_host() | ||
| 292 | * otherwise the caller must also call mmc_gpiod_request_cd_irq(). | ||
| 293 | * | ||
| 294 | * Returns zero on success, else an error. | ||
| 295 | */ | ||
| 296 | int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, | ||
| 297 | unsigned int idx, bool override_active_level, | ||
| 298 | unsigned int debounce) | ||
| 299 | { | ||
| 300 | struct mmc_gpio *ctx; | ||
| 301 | struct gpio_desc *desc; | ||
| 302 | int ret; | ||
| 303 | |||
| 304 | ret = mmc_gpio_alloc(host); | ||
| 305 | if (ret < 0) | ||
| 306 | return ret; | ||
| 307 | |||
| 308 | ctx = host->slot.handler_priv; | ||
| 309 | |||
| 310 | if (!con_id) | ||
| 311 | con_id = ctx->cd_label; | ||
| 312 | |||
| 313 | desc = devm_gpiod_get_index(host->parent, con_id, idx); | ||
| 314 | if (IS_ERR(desc)) | ||
| 315 | return PTR_ERR(desc); | ||
| 316 | |||
| 317 | ret = gpiod_direction_input(desc); | ||
| 318 | if (ret < 0) | ||
| 319 | return ret; | ||
| 320 | |||
| 321 | if (debounce) { | ||
| 322 | ret = gpiod_set_debounce(desc, debounce); | ||
| 323 | if (ret < 0) | ||
| 324 | return ret; | ||
| 325 | } | ||
| 326 | |||
| 327 | ctx->override_cd_active_level = override_active_level; | ||
| 328 | ctx->cd_gpio = desc; | ||
| 329 | |||
| 330 | return 0; | ||
| 331 | } | ||
| 332 | EXPORT_SYMBOL(mmc_gpiod_request_cd); | ||
| 333 | |||
| 334 | /** | ||
| 335 | * mmc_gpiod_free_cd - free the card-detection gpio descriptor | ||
| 336 | * @host: mmc host | ||
| 337 | * | ||
| 338 | * It's provided only for cases that client drivers need to manually free | ||
| 339 | * up the card-detection gpio requested by mmc_gpiod_request_cd(). | ||
| 340 | */ | ||
| 341 | void mmc_gpiod_free_cd(struct mmc_host *host) | ||
| 342 | { | ||
| 343 | struct mmc_gpio *ctx = host->slot.handler_priv; | ||
| 344 | |||
| 345 | if (!ctx || !ctx->cd_gpio) | ||
| 346 | return; | ||
| 347 | |||
| 348 | if (host->slot.cd_irq >= 0) { | ||
| 349 | devm_free_irq(&host->class_dev, host->slot.cd_irq, host); | ||
| 350 | host->slot.cd_irq = -EINVAL; | ||
| 351 | } | ||
| 352 | |||
| 353 | devm_gpiod_put(&host->class_dev, ctx->cd_gpio); | ||
| 354 | |||
| 355 | ctx->cd_gpio = NULL; | ||
| 356 | } | ||
| 357 | EXPORT_SYMBOL(mmc_gpiod_free_cd); | ||
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 1384f67abe21..8aaf8c1f3f63 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -263,7 +263,7 @@ config MMC_SDHCI_S3C_DMA | |||
| 263 | 263 | ||
| 264 | config MMC_SDHCI_BCM_KONA | 264 | config MMC_SDHCI_BCM_KONA |
| 265 | tristate "SDHCI support on Broadcom KONA platform" | 265 | tristate "SDHCI support on Broadcom KONA platform" |
| 266 | depends on ARCH_BCM | 266 | depends on ARCH_BCM_MOBILE |
| 267 | select MMC_SDHCI_PLTFM | 267 | select MMC_SDHCI_PLTFM |
| 268 | help | 268 | help |
| 269 | This selects the Broadcom Kona Secure Digital Host Controller | 269 | This selects the Broadcom Kona Secure Digital Host Controller |
| @@ -334,6 +334,19 @@ config MMC_ATMELMCI | |||
| 334 | 334 | ||
| 335 | If unsure, say N. | 335 | If unsure, say N. |
| 336 | 336 | ||
| 337 | config MMC_SDHCI_MSM | ||
| 338 | tristate "Qualcomm SDHCI Controller Support" | ||
| 339 | depends on ARCH_QCOM | ||
| 340 | depends on MMC_SDHCI_PLTFM | ||
| 341 | help | ||
| 342 | This selects the Secure Digital Host Controller Interface (SDHCI) | ||
| 343 | support present in Qualcomm SOCs. The controller supports | ||
| 344 | SD/MMC/SDIO devices. | ||
| 345 | |||
| 346 | If you have a controller with this interface, say Y or M here. | ||
| 347 | |||
| 348 | If unsure, say N. | ||
| 349 | |||
| 337 | config MMC_MSM | 350 | config MMC_MSM |
| 338 | tristate "Qualcomm SDCC Controller Support" | 351 | tristate "Qualcomm SDCC Controller Support" |
| 339 | depends on MMC && (ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50) | 352 | depends on MMC && (ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50) |
| @@ -580,14 +593,6 @@ config MMC_DW_EXYNOS | |||
| 580 | Synopsys DesignWare Memory Card Interface driver. Select this option | 593 | Synopsys DesignWare Memory Card Interface driver. Select this option |
| 581 | for platforms based on Exynos4 and Exynos5 SoC's. | 594 | for platforms based on Exynos4 and Exynos5 SoC's. |
| 582 | 595 | ||
| 583 | config MMC_DW_SOCFPGA | ||
| 584 | tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface" | ||
| 585 | depends on MMC_DW && MFD_SYSCON | ||
| 586 | select MMC_DW_PLTFM | ||
| 587 | help | ||
| 588 | This selects support for Altera SoCFPGA specific extensions to the | ||
| 589 | Synopsys DesignWare Memory Card Interface driver. | ||
| 590 | |||
| 591 | config MMC_DW_K3 | 596 | config MMC_DW_K3 |
| 592 | tristate "K3 specific extensions for Synopsys DW Memory Card Interface" | 597 | tristate "K3 specific extensions for Synopsys DW Memory Card Interface" |
| 593 | depends on MMC_DW | 598 | depends on MMC_DW |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 3483b6b6b880..0c8aa5e1e304 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
| @@ -43,7 +43,6 @@ obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o | |||
| 43 | obj-$(CONFIG_MMC_DW) += dw_mmc.o | 43 | obj-$(CONFIG_MMC_DW) += dw_mmc.o |
| 44 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o | 44 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o |
| 45 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o | 45 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o |
| 46 | obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o | ||
| 47 | obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o | 46 | obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o |
| 48 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o | 47 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o |
| 49 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o | 48 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o |
| @@ -64,6 +63,7 @@ obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o | |||
| 64 | obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o | 63 | obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o |
| 65 | obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o | 64 | obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o |
| 66 | obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhci-bcm2835.o | 65 | obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhci-bcm2835.o |
| 66 | obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o | ||
| 67 | 67 | ||
| 68 | ifeq ($(CONFIG_CB710_DEBUG),y) | 68 | ifeq ($(CONFIG_CB710_DEBUG),y) |
| 69 | CFLAGS-cb710-mmc += -DDEBUG | 69 | CFLAGS-cb710-mmc += -DDEBUG |
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index d6153740b77f..5d4c5e0fba2f 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c | |||
| @@ -1192,7 +1192,7 @@ static struct davinci_mmc_config | |||
| 1192 | struct device_node *np; | 1192 | struct device_node *np; |
| 1193 | struct davinci_mmc_config *pdata = pdev->dev.platform_data; | 1193 | struct davinci_mmc_config *pdata = pdev->dev.platform_data; |
| 1194 | const struct of_device_id *match = | 1194 | const struct of_device_id *match = |
| 1195 | of_match_device(of_match_ptr(davinci_mmc_dt_ids), &pdev->dev); | 1195 | of_match_device(davinci_mmc_dt_ids, &pdev->dev); |
| 1196 | u32 data; | 1196 | u32 data; |
| 1197 | 1197 | ||
| 1198 | np = pdev->dev.of_node; | 1198 | np = pdev->dev.of_node; |
| @@ -1468,7 +1468,7 @@ static struct platform_driver davinci_mmcsd_driver = { | |||
| 1468 | .name = "davinci_mmc", | 1468 | .name = "davinci_mmc", |
| 1469 | .owner = THIS_MODULE, | 1469 | .owner = THIS_MODULE, |
| 1470 | .pm = davinci_mmcsd_pm_ops, | 1470 | .pm = davinci_mmcsd_pm_ops, |
| 1471 | .of_match_table = of_match_ptr(davinci_mmc_dt_ids), | 1471 | .of_match_table = davinci_mmc_dt_ids, |
| 1472 | }, | 1472 | }, |
| 1473 | .remove = __exit_p(davinci_mmcsd_remove), | 1473 | .remove = __exit_p(davinci_mmcsd_remove), |
| 1474 | .id_table = davinci_mmc_devtype, | 1474 | .id_table = davinci_mmc_devtype, |
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c index f567c219cff4..650f9cc3f7a6 100644 --- a/drivers/mmc/host/dw_mmc-k3.c +++ b/drivers/mmc/host/dw_mmc-k3.c | |||
| @@ -50,6 +50,7 @@ static int dw_mci_k3_probe(struct platform_device *pdev) | |||
| 50 | return dw_mci_pltfm_register(pdev, drv_data); | 50 | return dw_mci_pltfm_register(pdev, drv_data); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | #ifdef CONFIG_PM_SLEEP | ||
| 53 | static int dw_mci_k3_suspend(struct device *dev) | 54 | static int dw_mci_k3_suspend(struct device *dev) |
| 54 | { | 55 | { |
| 55 | struct dw_mci *host = dev_get_drvdata(dev); | 56 | struct dw_mci *host = dev_get_drvdata(dev); |
| @@ -75,6 +76,7 @@ static int dw_mci_k3_resume(struct device *dev) | |||
| 75 | 76 | ||
| 76 | return dw_mci_resume(host); | 77 | return dw_mci_resume(host); |
| 77 | } | 78 | } |
| 79 | #endif /* CONFIG_PM_SLEEP */ | ||
| 78 | 80 | ||
| 79 | static SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume); | 81 | static SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume); |
| 80 | 82 | ||
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 5c4965655297..d4a47a9f5584 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c | |||
| @@ -25,13 +25,17 @@ | |||
| 25 | #include "dw_mmc.h" | 25 | #include "dw_mmc.h" |
| 26 | #include "dw_mmc-pltfm.h" | 26 | #include "dw_mmc-pltfm.h" |
| 27 | 27 | ||
| 28 | static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr) | 28 | static void dw_mci_pltfm_prepare_command(struct dw_mci *host, u32 *cmdr) |
| 29 | { | 29 | { |
| 30 | *cmdr |= SDMMC_CMD_USE_HOLD_REG; | 30 | *cmdr |= SDMMC_CMD_USE_HOLD_REG; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | static const struct dw_mci_drv_data rockchip_drv_data = { | 33 | static const struct dw_mci_drv_data rockchip_drv_data = { |
| 34 | .prepare_command = dw_mci_rockchip_prepare_command, | 34 | .prepare_command = dw_mci_pltfm_prepare_command, |
| 35 | }; | ||
| 36 | |||
| 37 | static const struct dw_mci_drv_data socfpga_drv_data = { | ||
| 38 | .prepare_command = dw_mci_pltfm_prepare_command, | ||
| 35 | }; | 39 | }; |
| 36 | 40 | ||
| 37 | int dw_mci_pltfm_register(struct platform_device *pdev, | 41 | int dw_mci_pltfm_register(struct platform_device *pdev, |
| @@ -92,6 +96,8 @@ static const struct of_device_id dw_mci_pltfm_match[] = { | |||
| 92 | { .compatible = "snps,dw-mshc", }, | 96 | { .compatible = "snps,dw-mshc", }, |
| 93 | { .compatible = "rockchip,rk2928-dw-mshc", | 97 | { .compatible = "rockchip,rk2928-dw-mshc", |
| 94 | .data = &rockchip_drv_data }, | 98 | .data = &rockchip_drv_data }, |
| 99 | { .compatible = "altr,socfpga-dw-mshc", | ||
| 100 | .data = &socfpga_drv_data }, | ||
| 95 | {}, | 101 | {}, |
| 96 | }; | 102 | }; |
| 97 | MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); | 103 | MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); |
| @@ -123,7 +129,7 @@ static struct platform_driver dw_mci_pltfm_driver = { | |||
| 123 | .remove = dw_mci_pltfm_remove, | 129 | .remove = dw_mci_pltfm_remove, |
| 124 | .driver = { | 130 | .driver = { |
| 125 | .name = "dw_mmc", | 131 | .name = "dw_mmc", |
| 126 | .of_match_table = of_match_ptr(dw_mci_pltfm_match), | 132 | .of_match_table = dw_mci_pltfm_match, |
| 127 | .pm = &dw_mci_pltfm_pmops, | 133 | .pm = &dw_mci_pltfm_pmops, |
| 128 | }, | 134 | }, |
| 129 | }; | 135 | }; |
diff --git a/drivers/mmc/host/dw_mmc-socfpga.c b/drivers/mmc/host/dw_mmc-socfpga.c deleted file mode 100644 index 3e8e53ae3302..000000000000 --- a/drivers/mmc/host/dw_mmc-socfpga.c +++ /dev/null | |||
| @@ -1,138 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Altera SoCFPGA Specific Extensions for Synopsys DW Multimedia Card Interface | ||
| 3 | * driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2012, Samsung Electronics Co., Ltd. | ||
| 6 | * Copyright (C) 2013 Altera Corporation | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * Taken from dw_mmc-exynos.c | ||
| 14 | */ | ||
| 15 | #include <linux/clk.h> | ||
| 16 | #include <linux/mfd/syscon.h> | ||
| 17 | #include <linux/mmc/host.h> | ||
| 18 | #include <linux/mmc/dw_mmc.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/of.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/regmap.h> | ||
| 23 | |||
| 24 | #include "dw_mmc.h" | ||
| 25 | #include "dw_mmc-pltfm.h" | ||
| 26 | |||
| 27 | #define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108 | ||
| 28 | #define DRV_CLK_PHASE_SHIFT_SEL_MASK 0x7 | ||
| 29 | #define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \ | ||
| 30 | ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0)) | ||
| 31 | |||
| 32 | /* SOCFPGA implementation specific driver private data */ | ||
| 33 | struct dw_mci_socfpga_priv_data { | ||
| 34 | u8 ciu_div; /* card interface unit divisor */ | ||
| 35 | u32 hs_timing; /* bitmask for CIU clock phase shift */ | ||
| 36 | struct regmap *sysreg; /* regmap for system manager register */ | ||
| 37 | }; | ||
| 38 | |||
| 39 | static int dw_mci_socfpga_priv_init(struct dw_mci *host) | ||
| 40 | { | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | static int dw_mci_socfpga_setup_clock(struct dw_mci *host) | ||
| 45 | { | ||
| 46 | struct dw_mci_socfpga_priv_data *priv = host->priv; | ||
| 47 | |||
| 48 | clk_disable_unprepare(host->ciu_clk); | ||
| 49 | regmap_write(priv->sysreg, SYSMGR_SDMMCGRP_CTRL_OFFSET, | ||
| 50 | priv->hs_timing); | ||
| 51 | clk_prepare_enable(host->ciu_clk); | ||
| 52 | |||
| 53 | host->bus_hz /= (priv->ciu_div + 1); | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | static void dw_mci_socfpga_prepare_command(struct dw_mci *host, u32 *cmdr) | ||
| 58 | { | ||
| 59 | struct dw_mci_socfpga_priv_data *priv = host->priv; | ||
| 60 | |||
| 61 | if (priv->hs_timing & DRV_CLK_PHASE_SHIFT_SEL_MASK) | ||
| 62 | *cmdr |= SDMMC_CMD_USE_HOLD_REG; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int dw_mci_socfpga_parse_dt(struct dw_mci *host) | ||
| 66 | { | ||
| 67 | struct dw_mci_socfpga_priv_data *priv; | ||
| 68 | struct device_node *np = host->dev->of_node; | ||
| 69 | u32 timing[2]; | ||
| 70 | u32 div = 0; | ||
| 71 | int ret; | ||
| 72 | |||
| 73 | priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); | ||
| 74 | if (!priv) { | ||
| 75 | dev_err(host->dev, "mem alloc failed for private data\n"); | ||
| 76 | return -ENOMEM; | ||
| 77 | } | ||
| 78 | |||
| 79 | priv->sysreg = syscon_regmap_lookup_by_compatible("altr,sys-mgr"); | ||
| 80 | if (IS_ERR(priv->sysreg)) { | ||
| 81 | dev_err(host->dev, "regmap for altr,sys-mgr lookup failed.\n"); | ||
| 82 | return PTR_ERR(priv->sysreg); | ||
| 83 | } | ||
| 84 | |||
| 85 | ret = of_property_read_u32(np, "altr,dw-mshc-ciu-div", &div); | ||
| 86 | if (ret) | ||
| 87 | dev_info(host->dev, "No dw-mshc-ciu-div specified, assuming 1"); | ||
| 88 | priv->ciu_div = div; | ||
| 89 | |||
| 90 | ret = of_property_read_u32_array(np, | ||
| 91 | "altr,dw-mshc-sdr-timing", timing, 2); | ||
| 92 | if (ret) | ||
| 93 | return ret; | ||
| 94 | |||
| 95 | priv->hs_timing = SYSMGR_SDMMC_CTRL_SET(timing[0], timing[1]); | ||
| 96 | host->priv = priv; | ||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | static const struct dw_mci_drv_data socfpga_drv_data = { | ||
| 101 | .init = dw_mci_socfpga_priv_init, | ||
| 102 | .setup_clock = dw_mci_socfpga_setup_clock, | ||
| 103 | .prepare_command = dw_mci_socfpga_prepare_command, | ||
| 104 | .parse_dt = dw_mci_socfpga_parse_dt, | ||
| 105 | }; | ||
| 106 | |||
| 107 | static const struct of_device_id dw_mci_socfpga_match[] = { | ||
| 108 | { .compatible = "altr,socfpga-dw-mshc", | ||
| 109 | .data = &socfpga_drv_data, }, | ||
| 110 | {}, | ||
| 111 | }; | ||
| 112 | MODULE_DEVICE_TABLE(of, dw_mci_socfpga_match); | ||
| 113 | |||
| 114 | static int dw_mci_socfpga_probe(struct platform_device *pdev) | ||
| 115 | { | ||
| 116 | const struct dw_mci_drv_data *drv_data; | ||
| 117 | const struct of_device_id *match; | ||
| 118 | |||
| 119 | match = of_match_node(dw_mci_socfpga_match, pdev->dev.of_node); | ||
| 120 | drv_data = match->data; | ||
| 121 | return dw_mci_pltfm_register(pdev, drv_data); | ||
| 122 | } | ||
| 123 | |||
| 124 | static struct platform_driver dw_mci_socfpga_pltfm_driver = { | ||
| 125 | .probe = dw_mci_socfpga_probe, | ||
| 126 | .remove = __exit_p(dw_mci_pltfm_remove), | ||
| 127 | .driver = { | ||
| 128 | .name = "dwmmc_socfpga", | ||
| 129 | .of_match_table = dw_mci_socfpga_match, | ||
| 130 | .pm = &dw_mci_pltfm_pmops, | ||
| 131 | }, | ||
| 132 | }; | ||
| 133 | |||
| 134 | module_platform_driver(dw_mci_socfpga_pltfm_driver); | ||
| 135 | |||
| 136 | MODULE_DESCRIPTION("Altera SOCFPGA Specific DW-MSHC Driver Extension"); | ||
| 137 | MODULE_LICENSE("GPL v2"); | ||
| 138 | MODULE_ALIAS("platform:dwmmc-socfpga"); | ||
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index c204b7d1532c..cced599d5aeb 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
| @@ -1345,7 +1345,7 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
| 1345 | 1345 | ||
| 1346 | if (!err) { | 1346 | if (!err) { |
| 1347 | if (!data->stop || mrq->sbc) { | 1347 | if (!data->stop || mrq->sbc) { |
| 1348 | if (mrq->sbc) | 1348 | if (mrq->sbc && data->stop) |
| 1349 | data->stop->error = 0; | 1349 | data->stop->error = 0; |
| 1350 | dw_mci_request_end(host, mrq); | 1350 | dw_mci_request_end(host, mrq); |
| 1351 | goto unlock; | 1351 | goto unlock; |
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 6bf24ab917e6..68349779c396 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h | |||
| @@ -185,7 +185,7 @@ | |||
| 185 | 185 | ||
| 186 | extern int dw_mci_probe(struct dw_mci *host); | 186 | extern int dw_mci_probe(struct dw_mci *host); |
| 187 | extern void dw_mci_remove(struct dw_mci *host); | 187 | extern void dw_mci_remove(struct dw_mci *host); |
| 188 | #ifdef CONFIG_PM | 188 | #ifdef CONFIG_PM_SLEEP |
| 189 | extern int dw_mci_suspend(struct dw_mci *host); | 189 | extern int dw_mci_suspend(struct dw_mci *host); |
| 190 | extern int dw_mci_resume(struct dw_mci *host); | 190 | extern int dw_mci_resume(struct dw_mci *host); |
| 191 | #endif | 191 | #endif |
| @@ -244,6 +244,7 @@ struct dw_mci_tuning_data { | |||
| 244 | * @prepare_command: handle CMD register extensions. | 244 | * @prepare_command: handle CMD register extensions. |
| 245 | * @set_ios: handle bus specific extensions. | 245 | * @set_ios: handle bus specific extensions. |
| 246 | * @parse_dt: parse implementation specific device tree properties. | 246 | * @parse_dt: parse implementation specific device tree properties. |
| 247 | * @execute_tuning: implementation specific tuning procedure. | ||
| 247 | * | 248 | * |
| 248 | * Provide controller implementation specific extensions. The usage of this | 249 | * Provide controller implementation specific extensions. The usage of this |
| 249 | * data structure is fully optional and usage of each member in this structure | 250 | * data structure is fully optional and usage of each member in this structure |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index b93122636531..771c60ab4a32 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
| @@ -921,6 +921,29 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, | |||
| 921 | { | 921 | { |
| 922 | void __iomem *base = host->base; | 922 | void __iomem *base = host->base; |
| 923 | bool sbc = (cmd == host->mrq->sbc); | 923 | bool sbc = (cmd == host->mrq->sbc); |
| 924 | bool busy_resp = host->variant->busy_detect && | ||
| 925 | (cmd->flags & MMC_RSP_BUSY); | ||
| 926 | |||
| 927 | /* Check if we need to wait for busy completion. */ | ||
| 928 | if (host->busy_status && (status & MCI_ST_CARDBUSY)) | ||
| 929 | return; | ||
| 930 | |||
| 931 | /* Enable busy completion if needed and supported. */ | ||
| 932 | if (!host->busy_status && busy_resp && | ||
| 933 | !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) && | ||
| 934 | (readl(base + MMCISTATUS) & MCI_ST_CARDBUSY)) { | ||
| 935 | writel(readl(base + MMCIMASK0) | MCI_ST_BUSYEND, | ||
| 936 | base + MMCIMASK0); | ||
| 937 | host->busy_status = status & (MCI_CMDSENT|MCI_CMDRESPEND); | ||
| 938 | return; | ||
| 939 | } | ||
| 940 | |||
| 941 | /* At busy completion, mask the IRQ and complete the request. */ | ||
| 942 | if (host->busy_status) { | ||
| 943 | writel(readl(base + MMCIMASK0) & ~MCI_ST_BUSYEND, | ||
| 944 | base + MMCIMASK0); | ||
| 945 | host->busy_status = 0; | ||
| 946 | } | ||
| 924 | 947 | ||
| 925 | host->cmd = NULL; | 948 | host->cmd = NULL; |
| 926 | 949 | ||
| @@ -1139,20 +1162,30 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) | |||
| 1139 | status &= ~MCI_IRQ1MASK; | 1162 | status &= ~MCI_IRQ1MASK; |
| 1140 | } | 1163 | } |
| 1141 | 1164 | ||
| 1165 | /* | ||
| 1166 | * We intentionally clear the MCI_ST_CARDBUSY IRQ here (if it's | ||
| 1167 | * enabled) since the HW seems to be triggering the IRQ on both | ||
| 1168 | * edges while monitoring DAT0 for busy completion. | ||
| 1169 | */ | ||
| 1142 | status &= readl(host->base + MMCIMASK0); | 1170 | status &= readl(host->base + MMCIMASK0); |
| 1143 | writel(status, host->base + MMCICLEAR); | 1171 | writel(status, host->base + MMCICLEAR); |
| 1144 | 1172 | ||
| 1145 | dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); | 1173 | dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); |
| 1146 | 1174 | ||
| 1175 | cmd = host->cmd; | ||
| 1176 | if ((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT| | ||
| 1177 | MCI_CMDSENT|MCI_CMDRESPEND) && cmd) | ||
| 1178 | mmci_cmd_irq(host, cmd, status); | ||
| 1179 | |||
| 1147 | data = host->data; | 1180 | data = host->data; |
| 1148 | if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR| | 1181 | if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR| |
| 1149 | MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND| | 1182 | MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND| |
| 1150 | MCI_DATABLOCKEND) && data) | 1183 | MCI_DATABLOCKEND) && data) |
| 1151 | mmci_data_irq(host, data, status); | 1184 | mmci_data_irq(host, data, status); |
| 1152 | 1185 | ||
| 1153 | cmd = host->cmd; | 1186 | /* Don't poll for busy completion in irq context. */ |
| 1154 | if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd) | 1187 | if (host->busy_status) |
| 1155 | mmci_cmd_irq(host, cmd, status); | 1188 | status &= ~MCI_ST_CARDBUSY; |
| 1156 | 1189 | ||
| 1157 | ret = 1; | 1190 | ret = 1; |
| 1158 | } while (status); | 1191 | } while (status); |
| @@ -1503,12 +1536,6 @@ static int mmci_probe(struct amba_device *dev, | |||
| 1503 | goto clk_disable; | 1536 | goto clk_disable; |
| 1504 | } | 1537 | } |
| 1505 | 1538 | ||
| 1506 | if (variant->busy_detect) { | ||
| 1507 | mmci_ops.card_busy = mmci_card_busy; | ||
| 1508 | mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE); | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | mmc->ops = &mmci_ops; | ||
| 1512 | /* | 1539 | /* |
| 1513 | * The ARM and ST versions of the block have slightly different | 1540 | * The ARM and ST versions of the block have slightly different |
| 1514 | * clock divider equations which means that the minimum divider | 1541 | * clock divider equations which means that the minimum divider |
| @@ -1542,6 +1569,15 @@ static int mmci_probe(struct amba_device *dev, | |||
| 1542 | mmc->caps = plat->capabilities; | 1569 | mmc->caps = plat->capabilities; |
| 1543 | mmc->caps2 = plat->capabilities2; | 1570 | mmc->caps2 = plat->capabilities2; |
| 1544 | 1571 | ||
| 1572 | if (variant->busy_detect) { | ||
| 1573 | mmci_ops.card_busy = mmci_card_busy; | ||
| 1574 | mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE); | ||
| 1575 | mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; | ||
| 1576 | mmc->max_busy_timeout = 0; | ||
| 1577 | } | ||
| 1578 | |||
| 1579 | mmc->ops = &mmci_ops; | ||
| 1580 | |||
| 1545 | /* We support these PM capabilities. */ | 1581 | /* We support these PM capabilities. */ |
| 1546 | mmc->pm_caps = MMC_PM_KEEP_POWER; | 1582 | mmc->pm_caps = MMC_PM_KEEP_POWER; |
| 1547 | 1583 | ||
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 84c0e59b792a..58b1b8896bf2 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h | |||
| @@ -140,6 +140,7 @@ | |||
| 140 | /* Extended status bits for the ST Micro variants */ | 140 | /* Extended status bits for the ST Micro variants */ |
| 141 | #define MCI_ST_SDIOITMASK (1 << 22) | 141 | #define MCI_ST_SDIOITMASK (1 << 22) |
| 142 | #define MCI_ST_CEATAENDMASK (1 << 23) | 142 | #define MCI_ST_CEATAENDMASK (1 << 23) |
| 143 | #define MCI_ST_BUSYEND (1 << 24) | ||
| 143 | 144 | ||
| 144 | #define MMCIMASK1 0x040 | 145 | #define MMCIMASK1 0x040 |
| 145 | #define MMCIFIFOCNT 0x048 | 146 | #define MMCIFIFOCNT 0x048 |
| @@ -187,6 +188,7 @@ struct mmci_host { | |||
| 187 | u32 pwr_reg; | 188 | u32 pwr_reg; |
| 188 | u32 clk_reg; | 189 | u32 clk_reg; |
| 189 | u32 datactrl_reg; | 190 | u32 datactrl_reg; |
| 191 | u32 busy_status; | ||
| 190 | bool vqmmc_enabled; | 192 | bool vqmmc_enabled; |
| 191 | struct mmci_platform_data *plat; | 193 | struct mmci_platform_data *plat; |
| 192 | struct variant_data *variant; | 194 | struct variant_data *variant; |
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 98b6b6ef7e5c..5c2e58b29305 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/omap-dma.h> | 26 | #include <linux/omap-dma.h> |
| 27 | #include <linux/mmc/host.h> | 27 | #include <linux/mmc/host.h> |
| 28 | #include <linux/mmc/card.h> | 28 | #include <linux/mmc/card.h> |
| 29 | #include <linux/mmc/mmc.h> | ||
| 29 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
| 30 | #include <linux/scatterlist.h> | 31 | #include <linux/scatterlist.h> |
| 31 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| @@ -130,7 +131,6 @@ struct mmc_omap_host { | |||
| 130 | u32 dma_rx_burst; | 131 | u32 dma_rx_burst; |
| 131 | struct dma_chan *dma_tx; | 132 | struct dma_chan *dma_tx; |
| 132 | u32 dma_tx_burst; | 133 | u32 dma_tx_burst; |
| 133 | struct resource *mem_res; | ||
| 134 | void __iomem *virt_base; | 134 | void __iomem *virt_base; |
| 135 | unsigned int phys_base; | 135 | unsigned int phys_base; |
| 136 | int irq; | 136 | int irq; |
| @@ -153,7 +153,6 @@ struct mmc_omap_host { | |||
| 153 | u32 total_bytes_left; | 153 | u32 total_bytes_left; |
| 154 | 154 | ||
| 155 | unsigned features; | 155 | unsigned features; |
| 156 | unsigned use_dma:1; | ||
| 157 | unsigned brs_received:1, dma_done:1; | 156 | unsigned brs_received:1, dma_done:1; |
| 158 | unsigned dma_in_use:1; | 157 | unsigned dma_in_use:1; |
| 159 | spinlock_t dma_lock; | 158 | spinlock_t dma_lock; |
| @@ -338,6 +337,7 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd) | |||
| 338 | u32 cmdreg; | 337 | u32 cmdreg; |
| 339 | u32 resptype; | 338 | u32 resptype; |
| 340 | u32 cmdtype; | 339 | u32 cmdtype; |
| 340 | u16 irq_mask; | ||
| 341 | 341 | ||
| 342 | host->cmd = cmd; | 342 | host->cmd = cmd; |
| 343 | 343 | ||
| @@ -390,12 +390,14 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd) | |||
| 390 | OMAP_MMC_WRITE(host, CTO, 200); | 390 | OMAP_MMC_WRITE(host, CTO, 200); |
| 391 | OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff); | 391 | OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff); |
| 392 | OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16); | 392 | OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16); |
| 393 | OMAP_MMC_WRITE(host, IE, | 393 | irq_mask = OMAP_MMC_STAT_A_EMPTY | OMAP_MMC_STAT_A_FULL | |
| 394 | OMAP_MMC_STAT_A_EMPTY | OMAP_MMC_STAT_A_FULL | | 394 | OMAP_MMC_STAT_CMD_CRC | OMAP_MMC_STAT_CMD_TOUT | |
| 395 | OMAP_MMC_STAT_CMD_CRC | OMAP_MMC_STAT_CMD_TOUT | | 395 | OMAP_MMC_STAT_DATA_CRC | OMAP_MMC_STAT_DATA_TOUT | |
| 396 | OMAP_MMC_STAT_DATA_CRC | OMAP_MMC_STAT_DATA_TOUT | | 396 | OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR | |
| 397 | OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR | | 397 | OMAP_MMC_STAT_END_OF_DATA; |
| 398 | OMAP_MMC_STAT_END_OF_DATA); | 398 | if (cmd->opcode == MMC_ERASE) |
| 399 | irq_mask &= ~OMAP_MMC_STAT_DATA_TOUT; | ||
| 400 | OMAP_MMC_WRITE(host, IE, irq_mask); | ||
| 399 | OMAP_MMC_WRITE(host, CMD, cmdreg); | 401 | OMAP_MMC_WRITE(host, CMD, cmdreg); |
| 400 | } | 402 | } |
| 401 | 403 | ||
| @@ -945,7 +947,7 @@ static void | |||
| 945 | mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) | 947 | mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) |
| 946 | { | 948 | { |
| 947 | struct mmc_data *data = req->data; | 949 | struct mmc_data *data = req->data; |
| 948 | int i, use_dma, block_size; | 950 | int i, use_dma = 1, block_size; |
| 949 | unsigned sg_len; | 951 | unsigned sg_len; |
| 950 | 952 | ||
| 951 | host->data = data; | 953 | host->data = data; |
| @@ -970,13 +972,10 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) | |||
| 970 | sg_len = (data->blocks == 1) ? 1 : data->sg_len; | 972 | sg_len = (data->blocks == 1) ? 1 : data->sg_len; |
| 971 | 973 | ||
| 972 | /* Only do DMA for entire blocks */ | 974 | /* Only do DMA for entire blocks */ |
| 973 | use_dma = host->use_dma; | 975 | for (i = 0; i < sg_len; i++) { |
| 974 | if (use_dma) { | 976 | if ((data->sg[i].length % block_size) != 0) { |
| 975 | for (i = 0; i < sg_len; i++) { | 977 | use_dma = 0; |
| 976 | if ((data->sg[i].length % block_size) != 0) { | 978 | break; |
| 977 | use_dma = 0; | ||
| 978 | break; | ||
| 979 | } | ||
| 980 | } | 979 | } |
| 981 | } | 980 | } |
| 982 | 981 | ||
| @@ -1239,7 +1238,7 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id) | |||
| 1239 | 1238 | ||
| 1240 | mmc->caps = 0; | 1239 | mmc->caps = 0; |
| 1241 | if (host->pdata->slots[id].wires >= 4) | 1240 | if (host->pdata->slots[id].wires >= 4) |
| 1242 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1241 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_ERASE; |
| 1243 | 1242 | ||
| 1244 | mmc->ops = &mmc_omap_ops; | 1243 | mmc->ops = &mmc_omap_ops; |
| 1245 | mmc->f_min = 400000; | 1244 | mmc->f_min = 400000; |
| @@ -1262,6 +1261,13 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id) | |||
| 1262 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 1261 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
| 1263 | mmc->max_seg_size = mmc->max_req_size; | 1262 | mmc->max_seg_size = mmc->max_req_size; |
| 1264 | 1263 | ||
| 1264 | if (slot->pdata->get_cover_state != NULL) { | ||
| 1265 | setup_timer(&slot->cover_timer, mmc_omap_cover_timer, | ||
| 1266 | (unsigned long)slot); | ||
| 1267 | tasklet_init(&slot->cover_tasklet, mmc_omap_cover_handler, | ||
| 1268 | (unsigned long)slot); | ||
| 1269 | } | ||
| 1270 | |||
| 1265 | r = mmc_add_host(mmc); | 1271 | r = mmc_add_host(mmc); |
| 1266 | if (r < 0) | 1272 | if (r < 0) |
| 1267 | goto err_remove_host; | 1273 | goto err_remove_host; |
| @@ -1278,11 +1284,6 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id) | |||
| 1278 | &dev_attr_cover_switch); | 1284 | &dev_attr_cover_switch); |
| 1279 | if (r < 0) | 1285 | if (r < 0) |
| 1280 | goto err_remove_slot_name; | 1286 | goto err_remove_slot_name; |
| 1281 | |||
| 1282 | setup_timer(&slot->cover_timer, mmc_omap_cover_timer, | ||
| 1283 | (unsigned long)slot); | ||
| 1284 | tasklet_init(&slot->cover_tasklet, mmc_omap_cover_handler, | ||
| 1285 | (unsigned long)slot); | ||
| 1286 | tasklet_schedule(&slot->cover_tasklet); | 1287 | tasklet_schedule(&slot->cover_tasklet); |
| 1287 | } | 1288 | } |
| 1288 | 1289 | ||
| @@ -1333,21 +1334,19 @@ static int mmc_omap_probe(struct platform_device *pdev) | |||
| 1333 | return -EPROBE_DEFER; | 1334 | return -EPROBE_DEFER; |
| 1334 | } | 1335 | } |
| 1335 | 1336 | ||
| 1336 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1337 | host = devm_kzalloc(&pdev->dev, sizeof(struct mmc_omap_host), |
| 1338 | GFP_KERNEL); | ||
| 1339 | if (host == NULL) | ||
| 1340 | return -ENOMEM; | ||
| 1341 | |||
| 1337 | irq = platform_get_irq(pdev, 0); | 1342 | irq = platform_get_irq(pdev, 0); |
| 1338 | if (res == NULL || irq < 0) | 1343 | if (irq < 0) |
| 1339 | return -ENXIO; | 1344 | return -ENXIO; |
| 1340 | 1345 | ||
| 1341 | res = request_mem_region(res->start, resource_size(res), | 1346 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1342 | pdev->name); | 1347 | host->virt_base = devm_ioremap_resource(&pdev->dev, res); |
| 1343 | if (res == NULL) | 1348 | if (IS_ERR(host->virt_base)) |
| 1344 | return -EBUSY; | 1349 | return PTR_ERR(host->virt_base); |
| 1345 | |||
| 1346 | host = kzalloc(sizeof(struct mmc_omap_host), GFP_KERNEL); | ||
| 1347 | if (host == NULL) { | ||
| 1348 | ret = -ENOMEM; | ||
| 1349 | goto err_free_mem_region; | ||
| 1350 | } | ||
| 1351 | 1350 | ||
| 1352 | INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work); | 1351 | INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work); |
| 1353 | INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work); | 1352 | INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work); |
| @@ -1369,20 +1368,11 @@ static int mmc_omap_probe(struct platform_device *pdev) | |||
| 1369 | platform_set_drvdata(pdev, host); | 1368 | platform_set_drvdata(pdev, host); |
| 1370 | 1369 | ||
| 1371 | host->id = pdev->id; | 1370 | host->id = pdev->id; |
| 1372 | host->mem_res = res; | ||
| 1373 | host->irq = irq; | ||
| 1374 | host->use_dma = 1; | ||
| 1375 | host->irq = irq; | 1371 | host->irq = irq; |
| 1376 | host->phys_base = host->mem_res->start; | 1372 | host->phys_base = res->start; |
| 1377 | host->virt_base = ioremap(res->start, resource_size(res)); | ||
| 1378 | if (!host->virt_base) | ||
| 1379 | goto err_ioremap; | ||
| 1380 | |||
| 1381 | host->iclk = clk_get(&pdev->dev, "ick"); | 1373 | host->iclk = clk_get(&pdev->dev, "ick"); |
| 1382 | if (IS_ERR(host->iclk)) { | 1374 | if (IS_ERR(host->iclk)) |
| 1383 | ret = PTR_ERR(host->iclk); | 1375 | return PTR_ERR(host->iclk); |
| 1384 | goto err_free_mmc_host; | ||
| 1385 | } | ||
| 1386 | clk_enable(host->iclk); | 1376 | clk_enable(host->iclk); |
| 1387 | 1377 | ||
| 1388 | host->fclk = clk_get(&pdev->dev, "fck"); | 1378 | host->fclk = clk_get(&pdev->dev, "fck"); |
| @@ -1460,12 +1450,6 @@ err_free_dma: | |||
| 1460 | err_free_iclk: | 1450 | err_free_iclk: |
| 1461 | clk_disable(host->iclk); | 1451 | clk_disable(host->iclk); |
| 1462 | clk_put(host->iclk); | 1452 | clk_put(host->iclk); |
| 1463 | err_free_mmc_host: | ||
| 1464 | iounmap(host->virt_base); | ||
| 1465 | err_ioremap: | ||
| 1466 | kfree(host); | ||
| 1467 | err_free_mem_region: | ||
| 1468 | release_mem_region(res->start, resource_size(res)); | ||
| 1469 | return ret; | 1453 | return ret; |
| 1470 | } | 1454 | } |
| 1471 | 1455 | ||
| @@ -1493,13 +1477,8 @@ static int mmc_omap_remove(struct platform_device *pdev) | |||
| 1493 | if (host->dma_rx) | 1477 | if (host->dma_rx) |
| 1494 | dma_release_channel(host->dma_rx); | 1478 | dma_release_channel(host->dma_rx); |
| 1495 | 1479 | ||
| 1496 | iounmap(host->virt_base); | ||
| 1497 | release_mem_region(pdev->resource[0].start, | ||
| 1498 | pdev->resource[0].end - pdev->resource[0].start + 1); | ||
| 1499 | destroy_workqueue(host->mmc_omap_wq); | 1480 | destroy_workqueue(host->mmc_omap_wq); |
| 1500 | 1481 | ||
| 1501 | kfree(host); | ||
| 1502 | |||
| 1503 | return 0; | 1482 | return 0; |
| 1504 | } | 1483 | } |
| 1505 | 1484 | ||
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index dbd32ad3b749..e91ee21549d0 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | /* OMAP HSMMC Host Controller Registers */ | 45 | /* OMAP HSMMC Host Controller Registers */ |
| 46 | #define OMAP_HSMMC_SYSSTATUS 0x0014 | 46 | #define OMAP_HSMMC_SYSSTATUS 0x0014 |
| 47 | #define OMAP_HSMMC_CON 0x002C | 47 | #define OMAP_HSMMC_CON 0x002C |
| 48 | #define OMAP_HSMMC_SDMASA 0x0100 | ||
| 48 | #define OMAP_HSMMC_BLK 0x0104 | 49 | #define OMAP_HSMMC_BLK 0x0104 |
| 49 | #define OMAP_HSMMC_ARG 0x0108 | 50 | #define OMAP_HSMMC_ARG 0x0108 |
| 50 | #define OMAP_HSMMC_CMD 0x010C | 51 | #define OMAP_HSMMC_CMD 0x010C |
| @@ -58,6 +59,7 @@ | |||
| 58 | #define OMAP_HSMMC_STAT 0x0130 | 59 | #define OMAP_HSMMC_STAT 0x0130 |
| 59 | #define OMAP_HSMMC_IE 0x0134 | 60 | #define OMAP_HSMMC_IE 0x0134 |
| 60 | #define OMAP_HSMMC_ISE 0x0138 | 61 | #define OMAP_HSMMC_ISE 0x0138 |
| 62 | #define OMAP_HSMMC_AC12 0x013C | ||
| 61 | #define OMAP_HSMMC_CAPA 0x0140 | 63 | #define OMAP_HSMMC_CAPA 0x0140 |
| 62 | 64 | ||
| 63 | #define VS18 (1 << 26) | 65 | #define VS18 (1 << 26) |
| @@ -81,6 +83,7 @@ | |||
| 81 | #define DTO_MASK 0x000F0000 | 83 | #define DTO_MASK 0x000F0000 |
| 82 | #define DTO_SHIFT 16 | 84 | #define DTO_SHIFT 16 |
| 83 | #define INIT_STREAM (1 << 1) | 85 | #define INIT_STREAM (1 << 1) |
| 86 | #define ACEN_ACMD23 (2 << 2) | ||
| 84 | #define DP_SELECT (1 << 21) | 87 | #define DP_SELECT (1 << 21) |
| 85 | #define DDIR (1 << 4) | 88 | #define DDIR (1 << 4) |
| 86 | #define DMAE 0x1 | 89 | #define DMAE 0x1 |
| @@ -97,7 +100,6 @@ | |||
| 97 | #define SRC (1 << 25) | 100 | #define SRC (1 << 25) |
| 98 | #define SRD (1 << 26) | 101 | #define SRD (1 << 26) |
| 99 | #define SOFTRESET (1 << 1) | 102 | #define SOFTRESET (1 << 1) |
| 100 | #define RESETDONE (1 << 0) | ||
| 101 | 103 | ||
| 102 | /* Interrupt masks for IE and ISE register */ | 104 | /* Interrupt masks for IE and ISE register */ |
| 103 | #define CC_EN (1 << 0) | 105 | #define CC_EN (1 << 0) |
| @@ -112,13 +114,21 @@ | |||
| 112 | #define DTO_EN (1 << 20) | 114 | #define DTO_EN (1 << 20) |
| 113 | #define DCRC_EN (1 << 21) | 115 | #define DCRC_EN (1 << 21) |
| 114 | #define DEB_EN (1 << 22) | 116 | #define DEB_EN (1 << 22) |
| 117 | #define ACE_EN (1 << 24) | ||
| 115 | #define CERR_EN (1 << 28) | 118 | #define CERR_EN (1 << 28) |
| 116 | #define BADA_EN (1 << 29) | 119 | #define BADA_EN (1 << 29) |
| 117 | 120 | ||
| 118 | #define INT_EN_MASK (BADA_EN | CERR_EN | DEB_EN | DCRC_EN |\ | 121 | #define INT_EN_MASK (BADA_EN | CERR_EN | ACE_EN | DEB_EN | DCRC_EN |\ |
| 119 | DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \ | 122 | DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \ |
| 120 | BRR_EN | BWR_EN | TC_EN | CC_EN) | 123 | BRR_EN | BWR_EN | TC_EN | CC_EN) |
| 121 | 124 | ||
| 125 | #define CNI (1 << 7) | ||
| 126 | #define ACIE (1 << 4) | ||
| 127 | #define ACEB (1 << 3) | ||
| 128 | #define ACCE (1 << 2) | ||
| 129 | #define ACTO (1 << 1) | ||
| 130 | #define ACNE (1 << 0) | ||
| 131 | |||
| 122 | #define MMC_AUTOSUSPEND_DELAY 100 | 132 | #define MMC_AUTOSUSPEND_DELAY 100 |
| 123 | #define MMC_TIMEOUT_MS 20 /* 20 mSec */ | 133 | #define MMC_TIMEOUT_MS 20 /* 20 mSec */ |
| 124 | #define MMC_TIMEOUT_US 20000 /* 20000 micro Sec */ | 134 | #define MMC_TIMEOUT_US 20000 /* 20000 micro Sec */ |
| @@ -126,6 +136,11 @@ | |||
| 126 | #define OMAP_MMC_MAX_CLOCK 52000000 | 136 | #define OMAP_MMC_MAX_CLOCK 52000000 |
| 127 | #define DRIVER_NAME "omap_hsmmc" | 137 | #define DRIVER_NAME "omap_hsmmc" |
| 128 | 138 | ||
| 139 | #define VDD_1V8 1800000 /* 180000 uV */ | ||
| 140 | #define VDD_3V0 3000000 /* 300000 uV */ | ||
| 141 | #define VDD_165_195 (ffs(MMC_VDD_165_195) - 1) | ||
| 142 | |||
| 143 | #define AUTO_CMD23 (1 << 1) /* Auto CMD23 support */ | ||
| 129 | /* | 144 | /* |
| 130 | * One controller can have multiple slots, like on some omap boards using | 145 | * One controller can have multiple slots, like on some omap boards using |
| 131 | * omap.c controller driver. Luckily this is not currently done on any known | 146 | * omap.c controller driver. Luckily this is not currently done on any known |
| @@ -164,7 +179,8 @@ struct omap_hsmmc_host { | |||
| 164 | */ | 179 | */ |
| 165 | struct regulator *vcc; | 180 | struct regulator *vcc; |
| 166 | struct regulator *vcc_aux; | 181 | struct regulator *vcc_aux; |
| 167 | int pbias_disable; | 182 | struct regulator *pbias; |
| 183 | bool pbias_enabled; | ||
| 168 | void __iomem *base; | 184 | void __iomem *base; |
| 169 | resource_size_t mapbase; | 185 | resource_size_t mapbase; |
| 170 | spinlock_t irq_lock; /* Prevent races with irq handler */ | 186 | spinlock_t irq_lock; /* Prevent races with irq handler */ |
| @@ -188,10 +204,19 @@ struct omap_hsmmc_host { | |||
| 188 | int reqs_blocked; | 204 | int reqs_blocked; |
| 189 | int use_reg; | 205 | int use_reg; |
| 190 | int req_in_progress; | 206 | int req_in_progress; |
| 207 | unsigned long clk_rate; | ||
| 208 | unsigned int flags; | ||
| 191 | struct omap_hsmmc_next next_data; | 209 | struct omap_hsmmc_next next_data; |
| 192 | struct omap_mmc_platform_data *pdata; | 210 | struct omap_mmc_platform_data *pdata; |
| 193 | }; | 211 | }; |
| 194 | 212 | ||
| 213 | struct omap_mmc_of_data { | ||
| 214 | u32 reg_offset; | ||
| 215 | u8 controller_flags; | ||
| 216 | }; | ||
| 217 | |||
| 218 | static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host); | ||
| 219 | |||
| 195 | static int omap_hsmmc_card_detect(struct device *dev, int slot) | 220 | static int omap_hsmmc_card_detect(struct device *dev, int slot) |
| 196 | { | 221 | { |
| 197 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 222 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
| @@ -261,17 +286,19 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on, | |||
| 261 | */ | 286 | */ |
| 262 | if (!host->vcc) | 287 | if (!host->vcc) |
| 263 | return 0; | 288 | return 0; |
| 264 | /* | ||
| 265 | * With DT, never turn OFF the regulator for MMC1. This is because | ||
| 266 | * the pbias cell programming support is still missing when | ||
| 267 | * booting with Device tree | ||
| 268 | */ | ||
| 269 | if (host->pbias_disable && !vdd) | ||
| 270 | return 0; | ||
| 271 | 289 | ||
| 272 | if (mmc_slot(host).before_set_reg) | 290 | if (mmc_slot(host).before_set_reg) |
| 273 | mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); | 291 | mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); |
| 274 | 292 | ||
| 293 | if (host->pbias) { | ||
| 294 | if (host->pbias_enabled == 1) { | ||
| 295 | ret = regulator_disable(host->pbias); | ||
| 296 | if (!ret) | ||
| 297 | host->pbias_enabled = 0; | ||
| 298 | } | ||
| 299 | regulator_set_voltage(host->pbias, VDD_3V0, VDD_3V0); | ||
| 300 | } | ||
| 301 | |||
| 275 | /* | 302 | /* |
| 276 | * Assume Vcc regulator is used only to power the card ... OMAP | 303 | * Assume Vcc regulator is used only to power the card ... OMAP |
| 277 | * VDDS is used to power the pins, optionally with a transceiver to | 304 | * VDDS is used to power the pins, optionally with a transceiver to |
| @@ -286,11 +313,12 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on, | |||
| 286 | * chips/cards need an interface voltage rail too. | 313 | * chips/cards need an interface voltage rail too. |
| 287 | */ | 314 | */ |
| 288 | if (power_on) { | 315 | if (power_on) { |
| 289 | ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); | 316 | if (host->vcc) |
| 317 | ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); | ||
| 290 | /* Enable interface voltage rail, if needed */ | 318 | /* Enable interface voltage rail, if needed */ |
| 291 | if (ret == 0 && host->vcc_aux) { | 319 | if (ret == 0 && host->vcc_aux) { |
| 292 | ret = regulator_enable(host->vcc_aux); | 320 | ret = regulator_enable(host->vcc_aux); |
| 293 | if (ret < 0) | 321 | if (ret < 0 && host->vcc) |
| 294 | ret = mmc_regulator_set_ocr(host->mmc, | 322 | ret = mmc_regulator_set_ocr(host->mmc, |
| 295 | host->vcc, 0); | 323 | host->vcc, 0); |
| 296 | } | 324 | } |
| @@ -298,16 +326,34 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on, | |||
| 298 | /* Shut down the rail */ | 326 | /* Shut down the rail */ |
| 299 | if (host->vcc_aux) | 327 | if (host->vcc_aux) |
| 300 | ret = regulator_disable(host->vcc_aux); | 328 | ret = regulator_disable(host->vcc_aux); |
| 301 | if (!ret) { | 329 | if (host->vcc) { |
| 302 | /* Then proceed to shut down the local regulator */ | 330 | /* Then proceed to shut down the local regulator */ |
| 303 | ret = mmc_regulator_set_ocr(host->mmc, | 331 | ret = mmc_regulator_set_ocr(host->mmc, |
| 304 | host->vcc, 0); | 332 | host->vcc, 0); |
| 305 | } | 333 | } |
| 306 | } | 334 | } |
| 307 | 335 | ||
| 336 | if (host->pbias) { | ||
| 337 | if (vdd <= VDD_165_195) | ||
| 338 | ret = regulator_set_voltage(host->pbias, VDD_1V8, | ||
| 339 | VDD_1V8); | ||
| 340 | else | ||
| 341 | ret = regulator_set_voltage(host->pbias, VDD_3V0, | ||
| 342 | VDD_3V0); | ||
| 343 | if (ret < 0) | ||
| 344 | goto error_set_power; | ||
| 345 | |||
| 346 | if (host->pbias_enabled == 0) { | ||
| 347 | ret = regulator_enable(host->pbias); | ||
| 348 | if (!ret) | ||
| 349 | host->pbias_enabled = 1; | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 308 | if (mmc_slot(host).after_set_reg) | 353 | if (mmc_slot(host).after_set_reg) |
| 309 | mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); | 354 | mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); |
| 310 | 355 | ||
| 356 | error_set_power: | ||
| 311 | return ret; | 357 | return ret; |
| 312 | } | 358 | } |
| 313 | 359 | ||
| @@ -316,12 +362,12 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | |||
| 316 | struct regulator *reg; | 362 | struct regulator *reg; |
| 317 | int ocr_value = 0; | 363 | int ocr_value = 0; |
| 318 | 364 | ||
| 319 | reg = regulator_get(host->dev, "vmmc"); | 365 | reg = devm_regulator_get(host->dev, "vmmc"); |
| 320 | if (IS_ERR(reg)) { | 366 | if (IS_ERR(reg)) { |
| 321 | dev_err(host->dev, "vmmc regulator missing\n"); | 367 | dev_err(host->dev, "unable to get vmmc regulator %ld\n", |
| 368 | PTR_ERR(reg)); | ||
| 322 | return PTR_ERR(reg); | 369 | return PTR_ERR(reg); |
| 323 | } else { | 370 | } else { |
| 324 | mmc_slot(host).set_power = omap_hsmmc_set_power; | ||
| 325 | host->vcc = reg; | 371 | host->vcc = reg; |
| 326 | ocr_value = mmc_regulator_get_ocrmask(reg); | 372 | ocr_value = mmc_regulator_get_ocrmask(reg); |
| 327 | if (!mmc_slot(host).ocr_mask) { | 373 | if (!mmc_slot(host).ocr_mask) { |
| @@ -334,31 +380,29 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | |||
| 334 | return -EINVAL; | 380 | return -EINVAL; |
| 335 | } | 381 | } |
| 336 | } | 382 | } |
| 383 | } | ||
| 384 | mmc_slot(host).set_power = omap_hsmmc_set_power; | ||
| 337 | 385 | ||
| 338 | /* Allow an aux regulator */ | 386 | /* Allow an aux regulator */ |
| 339 | reg = regulator_get(host->dev, "vmmc_aux"); | 387 | reg = devm_regulator_get_optional(host->dev, "vmmc_aux"); |
| 340 | host->vcc_aux = IS_ERR(reg) ? NULL : reg; | 388 | host->vcc_aux = IS_ERR(reg) ? NULL : reg; |
| 341 | 389 | ||
| 342 | /* For eMMC do not power off when not in sleep state */ | 390 | reg = devm_regulator_get_optional(host->dev, "pbias"); |
| 343 | if (mmc_slot(host).no_regulator_off_init) | 391 | host->pbias = IS_ERR(reg) ? NULL : reg; |
| 344 | return 0; | ||
| 345 | /* | ||
| 346 | * UGLY HACK: workaround regulator framework bugs. | ||
| 347 | * When the bootloader leaves a supply active, it's | ||
| 348 | * initialized with zero usecount ... and we can't | ||
| 349 | * disable it without first enabling it. Until the | ||
| 350 | * framework is fixed, we need a workaround like this | ||
| 351 | * (which is safe for MMC, but not in general). | ||
| 352 | */ | ||
| 353 | if (regulator_is_enabled(host->vcc) > 0 || | ||
| 354 | (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) { | ||
| 355 | int vdd = ffs(mmc_slot(host).ocr_mask) - 1; | ||
| 356 | 392 | ||
| 357 | mmc_slot(host).set_power(host->dev, host->slot_id, | 393 | /* For eMMC do not power off when not in sleep state */ |
| 358 | 1, vdd); | 394 | if (mmc_slot(host).no_regulator_off_init) |
| 359 | mmc_slot(host).set_power(host->dev, host->slot_id, | 395 | return 0; |
| 360 | 0, 0); | 396 | /* |
| 361 | } | 397 | * To disable boot_on regulator, enable regulator |
| 398 | * to increase usecount and then disable it. | ||
| 399 | */ | ||
| 400 | if ((host->vcc && regulator_is_enabled(host->vcc) > 0) || | ||
| 401 | (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) { | ||
| 402 | int vdd = ffs(mmc_slot(host).ocr_mask) - 1; | ||
| 403 | |||
| 404 | mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd); | ||
| 405 | mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); | ||
| 362 | } | 406 | } |
| 363 | 407 | ||
| 364 | return 0; | 408 | return 0; |
| @@ -366,8 +410,6 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | |||
| 366 | 410 | ||
| 367 | static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) | 411 | static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) |
| 368 | { | 412 | { |
| 369 | regulator_put(host->vcc); | ||
| 370 | regulator_put(host->vcc_aux); | ||
| 371 | mmc_slot(host).set_power = NULL; | 413 | mmc_slot(host).set_power = NULL; |
| 372 | } | 414 | } |
| 373 | 415 | ||
| @@ -605,9 +647,6 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | |||
| 605 | u32 hctl, capa; | 647 | u32 hctl, capa; |
| 606 | unsigned long timeout; | 648 | unsigned long timeout; |
| 607 | 649 | ||
| 608 | if (!OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) | ||
| 609 | return 1; | ||
| 610 | |||
| 611 | if (host->con == OMAP_HSMMC_READ(host->base, CON) && | 650 | if (host->con == OMAP_HSMMC_READ(host->base, CON) && |
| 612 | host->hctl == OMAP_HSMMC_READ(host->base, HCTL) && | 651 | host->hctl == OMAP_HSMMC_READ(host->base, HCTL) && |
| 613 | host->sysctl == OMAP_HSMMC_READ(host->base, SYSCTL) && | 652 | host->sysctl == OMAP_HSMMC_READ(host->base, SYSCTL) && |
| @@ -787,6 +826,11 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, | |||
| 787 | 826 | ||
| 788 | cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22); | 827 | cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22); |
| 789 | 828 | ||
| 829 | if ((host->flags & AUTO_CMD23) && mmc_op_multi(cmd->opcode) && | ||
| 830 | host->mrq->sbc) { | ||
| 831 | cmdreg |= ACEN_ACMD23; | ||
| 832 | OMAP_HSMMC_WRITE(host->base, SDMASA, host->mrq->sbc->arg); | ||
| 833 | } | ||
| 790 | if (data) { | 834 | if (data) { |
| 791 | cmdreg |= DP_SELECT | MSBS | BCE; | 835 | cmdreg |= DP_SELECT | MSBS | BCE; |
| 792 | if (data->flags & MMC_DATA_READ) | 836 | if (data->flags & MMC_DATA_READ) |
| @@ -864,11 +908,10 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) | |||
| 864 | else | 908 | else |
| 865 | data->bytes_xfered = 0; | 909 | data->bytes_xfered = 0; |
| 866 | 910 | ||
| 867 | if (!data->stop) { | 911 | if (data->stop && (data->error || !host->mrq->sbc)) |
| 912 | omap_hsmmc_start_command(host, data->stop, NULL); | ||
| 913 | else | ||
| 868 | omap_hsmmc_request_done(host, data->mrq); | 914 | omap_hsmmc_request_done(host, data->mrq); |
| 869 | return; | ||
| 870 | } | ||
| 871 | omap_hsmmc_start_command(host, data->stop, NULL); | ||
| 872 | } | 915 | } |
| 873 | 916 | ||
| 874 | /* | 917 | /* |
| @@ -879,6 +922,14 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) | |||
| 879 | { | 922 | { |
| 880 | host->cmd = NULL; | 923 | host->cmd = NULL; |
| 881 | 924 | ||
| 925 | if (host->mrq->sbc && (host->cmd == host->mrq->sbc) && | ||
| 926 | !host->mrq->sbc->error && !(host->flags & AUTO_CMD23)) { | ||
| 927 | omap_hsmmc_start_dma_transfer(host); | ||
| 928 | omap_hsmmc_start_command(host, host->mrq->cmd, | ||
| 929 | host->mrq->data); | ||
| 930 | return; | ||
| 931 | } | ||
| 932 | |||
| 882 | if (cmd->flags & MMC_RSP_PRESENT) { | 933 | if (cmd->flags & MMC_RSP_PRESENT) { |
| 883 | if (cmd->flags & MMC_RSP_136) { | 934 | if (cmd->flags & MMC_RSP_136) { |
| 884 | /* response type 2 */ | 935 | /* response type 2 */ |
| @@ -892,7 +943,7 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) | |||
| 892 | } | 943 | } |
| 893 | } | 944 | } |
| 894 | if ((host->data == NULL && !host->response_busy) || cmd->error) | 945 | if ((host->data == NULL && !host->response_busy) || cmd->error) |
| 895 | omap_hsmmc_request_done(host, cmd->mrq); | 946 | omap_hsmmc_request_done(host, host->mrq); |
| 896 | } | 947 | } |
| 897 | 948 | ||
| 898 | /* | 949 | /* |
| @@ -1015,6 +1066,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) | |||
| 1015 | { | 1066 | { |
| 1016 | struct mmc_data *data; | 1067 | struct mmc_data *data; |
| 1017 | int end_cmd = 0, end_trans = 0; | 1068 | int end_cmd = 0, end_trans = 0; |
| 1069 | int error = 0; | ||
| 1018 | 1070 | ||
| 1019 | data = host->data; | 1071 | data = host->data; |
| 1020 | dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); | 1072 | dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); |
| @@ -1029,6 +1081,20 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) | |||
| 1029 | else if (status & (CCRC_EN | DCRC_EN)) | 1081 | else if (status & (CCRC_EN | DCRC_EN)) |
| 1030 | hsmmc_command_incomplete(host, -EILSEQ, end_cmd); | 1082 | hsmmc_command_incomplete(host, -EILSEQ, end_cmd); |
| 1031 | 1083 | ||
| 1084 | if (status & ACE_EN) { | ||
| 1085 | u32 ac12; | ||
| 1086 | ac12 = OMAP_HSMMC_READ(host->base, AC12); | ||
| 1087 | if (!(ac12 & ACNE) && host->mrq->sbc) { | ||
| 1088 | end_cmd = 1; | ||
| 1089 | if (ac12 & ACTO) | ||
| 1090 | error = -ETIMEDOUT; | ||
| 1091 | else if (ac12 & (ACCE | ACEB | ACIE)) | ||
| 1092 | error = -EILSEQ; | ||
| 1093 | host->mrq->sbc->error = error; | ||
| 1094 | hsmmc_command_incomplete(host, error, end_cmd); | ||
| 1095 | } | ||
| 1096 | dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12); | ||
| 1097 | } | ||
| 1032 | if (host->data || host->response_busy) { | 1098 | if (host->data || host->response_busy) { |
| 1033 | end_trans = !end_cmd; | 1099 | end_trans = !end_cmd; |
| 1034 | host->response_busy = 0; | 1100 | host->response_busy = 0; |
| @@ -1236,8 +1302,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, | |||
| 1236 | } | 1302 | } |
| 1237 | 1303 | ||
| 1238 | /* Check if next job is already prepared */ | 1304 | /* Check if next job is already prepared */ |
| 1239 | if (next || | 1305 | if (next || data->host_cookie != host->next_data.cookie) { |
| 1240 | (!next && data->host_cookie != host->next_data.cookie)) { | ||
| 1241 | dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len, | 1306 | dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len, |
| 1242 | omap_hsmmc_get_dma_dir(host, data)); | 1307 | omap_hsmmc_get_dma_dir(host, data)); |
| 1243 | 1308 | ||
| @@ -1262,7 +1327,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, | |||
| 1262 | /* | 1327 | /* |
| 1263 | * Routine to configure and start DMA for the MMC card | 1328 | * Routine to configure and start DMA for the MMC card |
| 1264 | */ | 1329 | */ |
| 1265 | static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, | 1330 | static int omap_hsmmc_setup_dma_transfer(struct omap_hsmmc_host *host, |
| 1266 | struct mmc_request *req) | 1331 | struct mmc_request *req) |
| 1267 | { | 1332 | { |
| 1268 | struct dma_slave_config cfg; | 1333 | struct dma_slave_config cfg; |
| @@ -1321,8 +1386,6 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, | |||
| 1321 | 1386 | ||
| 1322 | host->dma_ch = 1; | 1387 | host->dma_ch = 1; |
| 1323 | 1388 | ||
| 1324 | dma_async_issue_pending(chan); | ||
| 1325 | |||
| 1326 | return 0; | 1389 | return 0; |
| 1327 | } | 1390 | } |
| 1328 | 1391 | ||
| @@ -1338,7 +1401,7 @@ static void set_data_timeout(struct omap_hsmmc_host *host, | |||
| 1338 | if (clkd == 0) | 1401 | if (clkd == 0) |
| 1339 | clkd = 1; | 1402 | clkd = 1; |
| 1340 | 1403 | ||
| 1341 | cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd); | 1404 | cycle_ns = 1000000000 / (host->clk_rate / clkd); |
| 1342 | timeout = timeout_ns / cycle_ns; | 1405 | timeout = timeout_ns / cycle_ns; |
| 1343 | timeout += timeout_clks; | 1406 | timeout += timeout_clks; |
| 1344 | if (timeout) { | 1407 | if (timeout) { |
| @@ -1363,6 +1426,21 @@ static void set_data_timeout(struct omap_hsmmc_host *host, | |||
| 1363 | OMAP_HSMMC_WRITE(host->base, SYSCTL, reg); | 1426 | OMAP_HSMMC_WRITE(host->base, SYSCTL, reg); |
| 1364 | } | 1427 | } |
| 1365 | 1428 | ||
| 1429 | static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host) | ||
| 1430 | { | ||
| 1431 | struct mmc_request *req = host->mrq; | ||
| 1432 | struct dma_chan *chan; | ||
| 1433 | |||
| 1434 | if (!req->data) | ||
| 1435 | return; | ||
| 1436 | OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz) | ||
| 1437 | | (req->data->blocks << 16)); | ||
| 1438 | set_data_timeout(host, req->data->timeout_ns, | ||
| 1439 | req->data->timeout_clks); | ||
| 1440 | chan = omap_hsmmc_get_dma_chan(host, req->data); | ||
| 1441 | dma_async_issue_pending(chan); | ||
| 1442 | } | ||
| 1443 | |||
| 1366 | /* | 1444 | /* |
| 1367 | * Configure block length for MMC/SD cards and initiate the transfer. | 1445 | * Configure block length for MMC/SD cards and initiate the transfer. |
| 1368 | */ | 1446 | */ |
| @@ -1383,12 +1461,8 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req) | |||
| 1383 | return 0; | 1461 | return 0; |
| 1384 | } | 1462 | } |
| 1385 | 1463 | ||
| 1386 | OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz) | ||
| 1387 | | (req->data->blocks << 16)); | ||
| 1388 | set_data_timeout(host, req->data->timeout_ns, req->data->timeout_clks); | ||
| 1389 | |||
| 1390 | if (host->use_dma) { | 1464 | if (host->use_dma) { |
| 1391 | ret = omap_hsmmc_start_dma_transfer(host, req); | 1465 | ret = omap_hsmmc_setup_dma_transfer(host, req); |
| 1392 | if (ret != 0) { | 1466 | if (ret != 0) { |
| 1393 | dev_err(mmc_dev(host->mmc), "MMC start dma failure\n"); | 1467 | dev_err(mmc_dev(host->mmc), "MMC start dma failure\n"); |
| 1394 | return ret; | 1468 | return ret; |
| @@ -1462,6 +1536,7 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) | |||
| 1462 | host->reqs_blocked = 0; | 1536 | host->reqs_blocked = 0; |
| 1463 | WARN_ON(host->mrq != NULL); | 1537 | WARN_ON(host->mrq != NULL); |
| 1464 | host->mrq = req; | 1538 | host->mrq = req; |
| 1539 | host->clk_rate = clk_get_rate(host->fclk); | ||
| 1465 | err = omap_hsmmc_prepare_data(host, req); | 1540 | err = omap_hsmmc_prepare_data(host, req); |
| 1466 | if (err) { | 1541 | if (err) { |
| 1467 | req->cmd->error = err; | 1542 | req->cmd->error = err; |
| @@ -1471,7 +1546,12 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) | |||
| 1471 | mmc_request_done(mmc, req); | 1546 | mmc_request_done(mmc, req); |
| 1472 | return; | 1547 | return; |
| 1473 | } | 1548 | } |
| 1549 | if (req->sbc && !(host->flags & AUTO_CMD23)) { | ||
| 1550 | omap_hsmmc_start_command(host, req->sbc, NULL); | ||
| 1551 | return; | ||
| 1552 | } | ||
| 1474 | 1553 | ||
| 1554 | omap_hsmmc_start_dma_transfer(host); | ||
| 1475 | omap_hsmmc_start_command(host, req->cmd, req->data); | 1555 | omap_hsmmc_start_command(host, req->cmd, req->data); |
| 1476 | } | 1556 | } |
| 1477 | 1557 | ||
| @@ -1509,13 +1589,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 1509 | * of external transceiver; but they all handle 1.8V. | 1589 | * of external transceiver; but they all handle 1.8V. |
| 1510 | */ | 1590 | */ |
| 1511 | if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) && | 1591 | if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) && |
| 1512 | (ios->vdd == DUAL_VOLT_OCR_BIT) && | 1592 | (ios->vdd == DUAL_VOLT_OCR_BIT)) { |
| 1513 | /* | ||
| 1514 | * With pbias cell programming missing, this | ||
| 1515 | * can't be allowed on MMC1 when booting with device | ||
| 1516 | * tree. | ||
| 1517 | */ | ||
| 1518 | !host->pbias_disable) { | ||
| 1519 | /* | 1593 | /* |
| 1520 | * The mmc_select_voltage fn of the core does | 1594 | * The mmc_select_voltage fn of the core does |
| 1521 | * not seem to set the power_mode to | 1595 | * not seem to set the power_mode to |
| @@ -1678,18 +1752,29 @@ static void omap_hsmmc_debugfs(struct mmc_host *mmc) | |||
| 1678 | #endif | 1752 | #endif |
| 1679 | 1753 | ||
| 1680 | #ifdef CONFIG_OF | 1754 | #ifdef CONFIG_OF |
| 1681 | static u16 omap4_reg_offset = 0x100; | 1755 | static const struct omap_mmc_of_data omap3_pre_es3_mmc_of_data = { |
| 1756 | /* See 35xx errata 2.1.1.128 in SPRZ278F */ | ||
| 1757 | .controller_flags = OMAP_HSMMC_BROKEN_MULTIBLOCK_READ, | ||
| 1758 | }; | ||
| 1759 | |||
| 1760 | static const struct omap_mmc_of_data omap4_mmc_of_data = { | ||
| 1761 | .reg_offset = 0x100, | ||
| 1762 | }; | ||
| 1682 | 1763 | ||
| 1683 | static const struct of_device_id omap_mmc_of_match[] = { | 1764 | static const struct of_device_id omap_mmc_of_match[] = { |
| 1684 | { | 1765 | { |
| 1685 | .compatible = "ti,omap2-hsmmc", | 1766 | .compatible = "ti,omap2-hsmmc", |
| 1686 | }, | 1767 | }, |
| 1687 | { | 1768 | { |
| 1769 | .compatible = "ti,omap3-pre-es3-hsmmc", | ||
| 1770 | .data = &omap3_pre_es3_mmc_of_data, | ||
| 1771 | }, | ||
| 1772 | { | ||
| 1688 | .compatible = "ti,omap3-hsmmc", | 1773 | .compatible = "ti,omap3-hsmmc", |
| 1689 | }, | 1774 | }, |
| 1690 | { | 1775 | { |
| 1691 | .compatible = "ti,omap4-hsmmc", | 1776 | .compatible = "ti,omap4-hsmmc", |
| 1692 | .data = &omap4_reg_offset, | 1777 | .data = &omap4_mmc_of_data, |
| 1693 | }, | 1778 | }, |
| 1694 | {}, | 1779 | {}, |
| 1695 | }; | 1780 | }; |
| @@ -1709,7 +1794,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) | |||
| 1709 | 1794 | ||
| 1710 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 1795 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
| 1711 | if (!pdata) | 1796 | if (!pdata) |
| 1712 | return NULL; /* out of memory */ | 1797 | return ERR_PTR(-ENOMEM); /* out of memory */ |
| 1713 | 1798 | ||
| 1714 | if (of_find_property(np, "ti,dual-volt", NULL)) | 1799 | if (of_find_property(np, "ti,dual-volt", NULL)) |
| 1715 | pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; | 1800 | pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; |
| @@ -1738,13 +1823,19 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) | |||
| 1738 | if (of_find_property(np, "ti,needs-special-hs-handling", NULL)) | 1823 | if (of_find_property(np, "ti,needs-special-hs-handling", NULL)) |
| 1739 | pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT; | 1824 | pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT; |
| 1740 | 1825 | ||
| 1826 | if (of_find_property(np, "keep-power-in-suspend", NULL)) | ||
| 1827 | pdata->slots[0].pm_caps |= MMC_PM_KEEP_POWER; | ||
| 1828 | |||
| 1829 | if (of_find_property(np, "enable-sdio-wakeup", NULL)) | ||
| 1830 | pdata->slots[0].pm_caps |= MMC_PM_WAKE_SDIO_IRQ; | ||
| 1831 | |||
| 1741 | return pdata; | 1832 | return pdata; |
| 1742 | } | 1833 | } |
| 1743 | #else | 1834 | #else |
| 1744 | static inline struct omap_mmc_platform_data | 1835 | static inline struct omap_mmc_platform_data |
| 1745 | *of_get_hsmmc_pdata(struct device *dev) | 1836 | *of_get_hsmmc_pdata(struct device *dev) |
| 1746 | { | 1837 | { |
| 1747 | return NULL; | 1838 | return ERR_PTR(-EINVAL); |
| 1748 | } | 1839 | } |
| 1749 | #endif | 1840 | #endif |
| 1750 | 1841 | ||
| @@ -1759,6 +1850,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 1759 | dma_cap_mask_t mask; | 1850 | dma_cap_mask_t mask; |
| 1760 | unsigned tx_req, rx_req; | 1851 | unsigned tx_req, rx_req; |
| 1761 | struct pinctrl *pinctrl; | 1852 | struct pinctrl *pinctrl; |
| 1853 | const struct omap_mmc_of_data *data; | ||
| 1762 | 1854 | ||
| 1763 | match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); | 1855 | match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); |
| 1764 | if (match) { | 1856 | if (match) { |
| @@ -1768,8 +1860,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 1768 | return PTR_ERR(pdata); | 1860 | return PTR_ERR(pdata); |
| 1769 | 1861 | ||
| 1770 | if (match->data) { | 1862 | if (match->data) { |
| 1771 | const u16 *offsetp = match->data; | 1863 | data = match->data; |
| 1772 | pdata->reg_offset = *offsetp; | 1864 | pdata->reg_offset = data->reg_offset; |
| 1865 | pdata->controller_flags |= data->controller_flags; | ||
| 1773 | } | 1866 | } |
| 1774 | } | 1867 | } |
| 1775 | 1868 | ||
| @@ -1814,6 +1907,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 1814 | host->base = ioremap(host->mapbase, SZ_4K); | 1907 | host->base = ioremap(host->mapbase, SZ_4K); |
| 1815 | host->power_mode = MMC_POWER_OFF; | 1908 | host->power_mode = MMC_POWER_OFF; |
| 1816 | host->next_data.cookie = 1; | 1909 | host->next_data.cookie = 1; |
| 1910 | host->pbias_enabled = 0; | ||
| 1817 | 1911 | ||
| 1818 | platform_set_drvdata(pdev, host); | 1912 | platform_set_drvdata(pdev, host); |
| 1819 | 1913 | ||
| @@ -1847,10 +1941,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 1847 | 1941 | ||
| 1848 | omap_hsmmc_context_save(host); | 1942 | omap_hsmmc_context_save(host); |
| 1849 | 1943 | ||
| 1850 | /* This can be removed once we support PBIAS with DT */ | ||
| 1851 | if (host->dev->of_node && res->start == 0x4809c000) | ||
| 1852 | host->pbias_disable = 1; | ||
| 1853 | |||
| 1854 | host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); | 1944 | host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); |
| 1855 | /* | 1945 | /* |
| 1856 | * MMC can still work without debounce clock. | 1946 | * MMC can still work without debounce clock. |
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index c46feda07d56..5fb994f9a653 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c | |||
| @@ -31,14 +31,9 @@ | |||
| 31 | #include <linux/mfd/rtsx_pci.h> | 31 | #include <linux/mfd/rtsx_pci.h> |
| 32 | #include <asm/unaligned.h> | 32 | #include <asm/unaligned.h> |
| 33 | 33 | ||
| 34 | /* SD Tuning Data Structure | 34 | struct realtek_next { |
| 35 | * Record continuous timing phase path | 35 | unsigned int sg_count; |
| 36 | */ | 36 | s32 cookie; |
| 37 | struct timing_phase_path { | ||
| 38 | int start; | ||
| 39 | int end; | ||
| 40 | int mid; | ||
| 41 | int len; | ||
| 42 | }; | 37 | }; |
| 43 | 38 | ||
| 44 | struct realtek_pci_sdmmc { | 39 | struct realtek_pci_sdmmc { |
| @@ -46,9 +41,18 @@ struct realtek_pci_sdmmc { | |||
| 46 | struct rtsx_pcr *pcr; | 41 | struct rtsx_pcr *pcr; |
| 47 | struct mmc_host *mmc; | 42 | struct mmc_host *mmc; |
| 48 | struct mmc_request *mrq; | 43 | struct mmc_request *mrq; |
| 49 | 44 | struct mmc_command *cmd; | |
| 50 | struct mutex host_mutex; | 45 | struct mmc_data *data; |
| 51 | 46 | ||
| 47 | spinlock_t lock; | ||
| 48 | struct timer_list timer; | ||
| 49 | struct tasklet_struct cmd_tasklet; | ||
| 50 | struct tasklet_struct data_tasklet; | ||
| 51 | struct tasklet_struct finish_tasklet; | ||
| 52 | |||
| 53 | u8 rsp_type; | ||
| 54 | u8 rsp_len; | ||
| 55 | int sg_count; | ||
| 52 | u8 ssc_depth; | 56 | u8 ssc_depth; |
| 53 | unsigned int clock; | 57 | unsigned int clock; |
| 54 | bool vpclk; | 58 | bool vpclk; |
| @@ -58,8 +62,13 @@ struct realtek_pci_sdmmc { | |||
| 58 | int power_state; | 62 | int power_state; |
| 59 | #define SDMMC_POWER_ON 1 | 63 | #define SDMMC_POWER_ON 1 |
| 60 | #define SDMMC_POWER_OFF 0 | 64 | #define SDMMC_POWER_OFF 0 |
| 65 | |||
| 66 | struct realtek_next next_data; | ||
| 61 | }; | 67 | }; |
| 62 | 68 | ||
| 69 | static int sd_start_multi_rw(struct realtek_pci_sdmmc *host, | ||
| 70 | struct mmc_request *mrq); | ||
| 71 | |||
| 63 | static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) | 72 | static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) |
| 64 | { | 73 | { |
| 65 | return &(host->pdev->dev); | 74 | return &(host->pdev->dev); |
| @@ -96,6 +105,95 @@ static void sd_print_debug_regs(struct realtek_pci_sdmmc *host) | |||
| 96 | #define sd_print_debug_regs(host) | 105 | #define sd_print_debug_regs(host) |
| 97 | #endif /* DEBUG */ | 106 | #endif /* DEBUG */ |
| 98 | 107 | ||
| 108 | static void sd_isr_done_transfer(struct platform_device *pdev) | ||
| 109 | { | ||
| 110 | struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); | ||
| 111 | |||
| 112 | spin_lock(&host->lock); | ||
| 113 | if (host->cmd) | ||
| 114 | tasklet_schedule(&host->cmd_tasklet); | ||
| 115 | if (host->data) | ||
| 116 | tasklet_schedule(&host->data_tasklet); | ||
| 117 | spin_unlock(&host->lock); | ||
| 118 | } | ||
| 119 | |||
| 120 | static void sd_request_timeout(unsigned long host_addr) | ||
| 121 | { | ||
| 122 | struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; | ||
| 123 | unsigned long flags; | ||
| 124 | |||
| 125 | spin_lock_irqsave(&host->lock, flags); | ||
| 126 | |||
| 127 | if (!host->mrq) { | ||
| 128 | dev_err(sdmmc_dev(host), "error: no request exist\n"); | ||
| 129 | goto out; | ||
| 130 | } | ||
| 131 | |||
| 132 | if (host->cmd) | ||
| 133 | host->cmd->error = -ETIMEDOUT; | ||
| 134 | if (host->data) | ||
| 135 | host->data->error = -ETIMEDOUT; | ||
| 136 | |||
| 137 | dev_dbg(sdmmc_dev(host), "timeout for request\n"); | ||
| 138 | |||
| 139 | out: | ||
| 140 | tasklet_schedule(&host->finish_tasklet); | ||
| 141 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 142 | } | ||
| 143 | |||
| 144 | static void sd_finish_request(unsigned long host_addr) | ||
| 145 | { | ||
| 146 | struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; | ||
| 147 | struct rtsx_pcr *pcr = host->pcr; | ||
| 148 | struct mmc_request *mrq; | ||
| 149 | struct mmc_command *cmd; | ||
| 150 | struct mmc_data *data; | ||
| 151 | unsigned long flags; | ||
| 152 | bool any_error; | ||
| 153 | |||
| 154 | spin_lock_irqsave(&host->lock, flags); | ||
| 155 | |||
| 156 | del_timer(&host->timer); | ||
| 157 | mrq = host->mrq; | ||
| 158 | if (!mrq) { | ||
| 159 | dev_err(sdmmc_dev(host), "error: no request need finish\n"); | ||
| 160 | goto out; | ||
| 161 | } | ||
| 162 | |||
| 163 | cmd = mrq->cmd; | ||
| 164 | data = mrq->data; | ||
| 165 | |||
| 166 | any_error = (mrq->sbc && mrq->sbc->error) || | ||
| 167 | (mrq->stop && mrq->stop->error) || | ||
| 168 | (cmd && cmd->error) || (data && data->error); | ||
| 169 | |||
| 170 | if (any_error) { | ||
| 171 | rtsx_pci_stop_cmd(pcr); | ||
| 172 | sd_clear_error(host); | ||
| 173 | } | ||
| 174 | |||
| 175 | if (data) { | ||
| 176 | if (any_error) | ||
| 177 | data->bytes_xfered = 0; | ||
| 178 | else | ||
| 179 | data->bytes_xfered = data->blocks * data->blksz; | ||
| 180 | |||
| 181 | if (!data->host_cookie) | ||
| 182 | rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, | ||
| 183 | data->flags & MMC_DATA_READ); | ||
| 184 | |||
| 185 | } | ||
| 186 | |||
| 187 | host->mrq = NULL; | ||
| 188 | host->cmd = NULL; | ||
| 189 | host->data = NULL; | ||
| 190 | |||
| 191 | out: | ||
| 192 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 193 | mutex_unlock(&pcr->pcr_mutex); | ||
| 194 | mmc_request_done(host->mmc, mrq); | ||
| 195 | } | ||
| 196 | |||
| 99 | static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, | 197 | static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, |
| 100 | u8 *buf, int buf_len, int timeout) | 198 | u8 *buf, int buf_len, int timeout) |
| 101 | { | 199 | { |
| @@ -213,8 +311,7 @@ static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, | |||
| 213 | return 0; | 311 | return 0; |
| 214 | } | 312 | } |
| 215 | 313 | ||
| 216 | static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | 314 | static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) |
| 217 | struct mmc_command *cmd) | ||
| 218 | { | 315 | { |
| 219 | struct rtsx_pcr *pcr = host->pcr; | 316 | struct rtsx_pcr *pcr = host->pcr; |
| 220 | u8 cmd_idx = (u8)cmd->opcode; | 317 | u8 cmd_idx = (u8)cmd->opcode; |
| @@ -222,11 +319,14 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | |||
| 222 | int err = 0; | 319 | int err = 0; |
| 223 | int timeout = 100; | 320 | int timeout = 100; |
| 224 | int i; | 321 | int i; |
| 225 | u8 *ptr; | ||
| 226 | int stat_idx = 0; | ||
| 227 | u8 rsp_type; | 322 | u8 rsp_type; |
| 228 | int rsp_len = 5; | 323 | int rsp_len = 5; |
| 229 | bool clock_toggled = false; | 324 | unsigned long flags; |
| 325 | |||
| 326 | if (host->cmd) | ||
| 327 | dev_err(sdmmc_dev(host), "error: cmd already exist\n"); | ||
| 328 | |||
| 329 | host->cmd = cmd; | ||
| 230 | 330 | ||
| 231 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", | 331 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", |
| 232 | __func__, cmd_idx, arg); | 332 | __func__, cmd_idx, arg); |
| @@ -261,6 +361,8 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | |||
| 261 | err = -EINVAL; | 361 | err = -EINVAL; |
| 262 | goto out; | 362 | goto out; |
| 263 | } | 363 | } |
| 364 | host->rsp_type = rsp_type; | ||
| 365 | host->rsp_len = rsp_len; | ||
| 264 | 366 | ||
| 265 | if (rsp_type == SD_RSP_TYPE_R1b) | 367 | if (rsp_type == SD_RSP_TYPE_R1b) |
| 266 | timeout = 3000; | 368 | timeout = 3000; |
| @@ -270,8 +372,6 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | |||
| 270 | 0xFF, SD_CLK_TOGGLE_EN); | 372 | 0xFF, SD_CLK_TOGGLE_EN); |
| 271 | if (err < 0) | 373 | if (err < 0) |
| 272 | goto out; | 374 | goto out; |
| 273 | |||
| 274 | clock_toggled = true; | ||
| 275 | } | 375 | } |
| 276 | 376 | ||
| 277 | rtsx_pci_init_cmd(pcr); | 377 | rtsx_pci_init_cmd(pcr); |
| @@ -295,25 +395,60 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | |||
| 295 | /* Read data from ping-pong buffer */ | 395 | /* Read data from ping-pong buffer */ |
| 296 | for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) | 396 | for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) |
| 297 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); | 397 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); |
| 298 | stat_idx = 16; | ||
| 299 | } else if (rsp_type != SD_RSP_TYPE_R0) { | 398 | } else if (rsp_type != SD_RSP_TYPE_R0) { |
| 300 | /* Read data from SD_CMDx registers */ | 399 | /* Read data from SD_CMDx registers */ |
| 301 | for (i = SD_CMD0; i <= SD_CMD4; i++) | 400 | for (i = SD_CMD0; i <= SD_CMD4; i++) |
| 302 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); | 401 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); |
| 303 | stat_idx = 5; | ||
| 304 | } | 402 | } |
| 305 | 403 | ||
| 306 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0); | 404 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0); |
| 307 | 405 | ||
| 308 | err = rtsx_pci_send_cmd(pcr, timeout); | 406 | mod_timer(&host->timer, jiffies + msecs_to_jiffies(timeout)); |
| 309 | if (err < 0) { | 407 | |
| 310 | sd_print_debug_regs(host); | 408 | spin_lock_irqsave(&pcr->lock, flags); |
| 311 | sd_clear_error(host); | 409 | pcr->trans_result = TRANS_NOT_READY; |
| 312 | dev_dbg(sdmmc_dev(host), | 410 | rtsx_pci_send_cmd_no_wait(pcr); |
| 313 | "rtsx_pci_send_cmd error (err = %d)\n", err); | 411 | spin_unlock_irqrestore(&pcr->lock, flags); |
| 412 | |||
| 413 | return; | ||
| 414 | |||
| 415 | out: | ||
| 416 | cmd->error = err; | ||
| 417 | tasklet_schedule(&host->finish_tasklet); | ||
| 418 | } | ||
| 419 | |||
| 420 | static void sd_get_rsp(unsigned long host_addr) | ||
| 421 | { | ||
| 422 | struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; | ||
| 423 | struct rtsx_pcr *pcr = host->pcr; | ||
| 424 | struct mmc_command *cmd; | ||
| 425 | int i, err = 0, stat_idx; | ||
| 426 | u8 *ptr, rsp_type; | ||
| 427 | unsigned long flags; | ||
| 428 | |||
| 429 | spin_lock_irqsave(&host->lock, flags); | ||
| 430 | |||
| 431 | cmd = host->cmd; | ||
| 432 | host->cmd = NULL; | ||
| 433 | |||
| 434 | if (!cmd) { | ||
| 435 | dev_err(sdmmc_dev(host), "error: cmd not exist\n"); | ||
| 314 | goto out; | 436 | goto out; |
| 315 | } | 437 | } |
| 316 | 438 | ||
| 439 | spin_lock(&pcr->lock); | ||
| 440 | if (pcr->trans_result == TRANS_NO_DEVICE) | ||
| 441 | err = -ENODEV; | ||
| 442 | else if (pcr->trans_result != TRANS_RESULT_OK) | ||
| 443 | err = -EINVAL; | ||
| 444 | spin_unlock(&pcr->lock); | ||
| 445 | |||
| 446 | if (err < 0) | ||
| 447 | goto out; | ||
| 448 | |||
| 449 | rsp_type = host->rsp_type; | ||
| 450 | stat_idx = host->rsp_len; | ||
| 451 | |||
| 317 | if (rsp_type == SD_RSP_TYPE_R0) { | 452 | if (rsp_type == SD_RSP_TYPE_R0) { |
| 318 | err = 0; | 453 | err = 0; |
| 319 | goto out; | 454 | goto out; |
| @@ -350,26 +485,106 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | |||
| 350 | cmd->resp[0]); | 485 | cmd->resp[0]); |
| 351 | } | 486 | } |
| 352 | 487 | ||
| 488 | if (cmd == host->mrq->sbc) { | ||
| 489 | sd_send_cmd(host, host->mrq->cmd); | ||
| 490 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 491 | return; | ||
| 492 | } | ||
| 493 | |||
| 494 | if (cmd == host->mrq->stop) | ||
| 495 | goto out; | ||
| 496 | |||
| 497 | if (cmd->data) { | ||
| 498 | sd_start_multi_rw(host, host->mrq); | ||
| 499 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 500 | return; | ||
| 501 | } | ||
| 502 | |||
| 353 | out: | 503 | out: |
| 354 | cmd->error = err; | 504 | cmd->error = err; |
| 355 | 505 | ||
| 356 | if (err && clock_toggled) | 506 | tasklet_schedule(&host->finish_tasklet); |
| 357 | rtsx_pci_write_register(pcr, SD_BUS_STAT, | 507 | spin_unlock_irqrestore(&host->lock, flags); |
| 358 | SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); | ||
| 359 | } | 508 | } |
| 360 | 509 | ||
| 361 | static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) | 510 | static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host, |
| 511 | struct mmc_data *data, struct realtek_next *next) | ||
| 512 | { | ||
| 513 | struct rtsx_pcr *pcr = host->pcr; | ||
| 514 | int read = data->flags & MMC_DATA_READ; | ||
| 515 | int sg_count = 0; | ||
| 516 | |||
| 517 | if (!next && data->host_cookie && | ||
| 518 | data->host_cookie != host->next_data.cookie) { | ||
| 519 | dev_err(sdmmc_dev(host), | ||
| 520 | "error: invalid cookie data[%d] host[%d]\n", | ||
| 521 | data->host_cookie, host->next_data.cookie); | ||
| 522 | data->host_cookie = 0; | ||
| 523 | } | ||
| 524 | |||
| 525 | if (next || (!next && data->host_cookie != host->next_data.cookie)) | ||
| 526 | sg_count = rtsx_pci_dma_map_sg(pcr, | ||
| 527 | data->sg, data->sg_len, read); | ||
| 528 | else | ||
| 529 | sg_count = host->next_data.sg_count; | ||
| 530 | |||
| 531 | if (next) { | ||
| 532 | next->sg_count = sg_count; | ||
| 533 | if (++next->cookie < 0) | ||
| 534 | next->cookie = 1; | ||
| 535 | data->host_cookie = next->cookie; | ||
| 536 | } | ||
| 537 | |||
| 538 | return sg_count; | ||
| 539 | } | ||
| 540 | |||
| 541 | static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, | ||
| 542 | bool is_first_req) | ||
| 543 | { | ||
| 544 | struct realtek_pci_sdmmc *host = mmc_priv(mmc); | ||
| 545 | struct mmc_data *data = mrq->data; | ||
| 546 | |||
| 547 | if (data->host_cookie) { | ||
| 548 | dev_err(sdmmc_dev(host), | ||
| 549 | "error: descard already cookie data[%d]\n", | ||
| 550 | data->host_cookie); | ||
| 551 | data->host_cookie = 0; | ||
| 552 | } | ||
| 553 | |||
| 554 | dev_dbg(sdmmc_dev(host), "dma sg prepared: %d\n", | ||
| 555 | sd_pre_dma_transfer(host, data, &host->next_data)); | ||
| 556 | } | ||
| 557 | |||
| 558 | static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, | ||
| 559 | int err) | ||
| 560 | { | ||
| 561 | struct realtek_pci_sdmmc *host = mmc_priv(mmc); | ||
| 562 | struct rtsx_pcr *pcr = host->pcr; | ||
| 563 | struct mmc_data *data = mrq->data; | ||
| 564 | int read = data->flags & MMC_DATA_READ; | ||
| 565 | |||
| 566 | rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read); | ||
| 567 | data->host_cookie = 0; | ||
| 568 | } | ||
| 569 | |||
| 570 | static int sd_start_multi_rw(struct realtek_pci_sdmmc *host, | ||
| 571 | struct mmc_request *mrq) | ||
| 362 | { | 572 | { |
| 363 | struct rtsx_pcr *pcr = host->pcr; | 573 | struct rtsx_pcr *pcr = host->pcr; |
| 364 | struct mmc_host *mmc = host->mmc; | 574 | struct mmc_host *mmc = host->mmc; |
| 365 | struct mmc_card *card = mmc->card; | 575 | struct mmc_card *card = mmc->card; |
| 366 | struct mmc_data *data = mrq->data; | 576 | struct mmc_data *data = mrq->data; |
| 367 | int uhs = mmc_card_uhs(card); | 577 | int uhs = mmc_card_uhs(card); |
| 368 | int read = (data->flags & MMC_DATA_READ) ? 1 : 0; | 578 | int read = data->flags & MMC_DATA_READ; |
| 369 | u8 cfg2, trans_mode; | 579 | u8 cfg2, trans_mode; |
| 370 | int err; | 580 | int err; |
| 371 | size_t data_len = data->blksz * data->blocks; | 581 | size_t data_len = data->blksz * data->blocks; |
| 372 | 582 | ||
| 583 | if (host->data) | ||
| 584 | dev_err(sdmmc_dev(host), "error: data already exist\n"); | ||
| 585 | |||
| 586 | host->data = data; | ||
| 587 | |||
| 373 | if (read) { | 588 | if (read) { |
| 374 | cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | | 589 | cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | |
| 375 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; | 590 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; |
| @@ -420,17 +635,56 @@ static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) | |||
| 420 | rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, | 635 | rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, |
| 421 | SD_TRANSFER_END, SD_TRANSFER_END); | 636 | SD_TRANSFER_END, SD_TRANSFER_END); |
| 422 | 637 | ||
| 638 | mod_timer(&host->timer, jiffies + 10 * HZ); | ||
| 423 | rtsx_pci_send_cmd_no_wait(pcr); | 639 | rtsx_pci_send_cmd_no_wait(pcr); |
| 424 | 640 | ||
| 425 | err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000); | 641 | err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read); |
| 426 | if (err < 0) { | 642 | if (err < 0) { |
| 427 | sd_clear_error(host); | 643 | data->error = err; |
| 428 | return err; | 644 | tasklet_schedule(&host->finish_tasklet); |
| 429 | } | 645 | } |
| 430 | |||
| 431 | return 0; | 646 | return 0; |
| 432 | } | 647 | } |
| 433 | 648 | ||
| 649 | static void sd_finish_multi_rw(unsigned long host_addr) | ||
| 650 | { | ||
| 651 | struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; | ||
| 652 | struct rtsx_pcr *pcr = host->pcr; | ||
| 653 | struct mmc_data *data; | ||
| 654 | int err = 0; | ||
| 655 | unsigned long flags; | ||
| 656 | |||
| 657 | spin_lock_irqsave(&host->lock, flags); | ||
| 658 | |||
| 659 | if (!host->data) { | ||
| 660 | dev_err(sdmmc_dev(host), "error: no data exist\n"); | ||
| 661 | goto out; | ||
| 662 | } | ||
| 663 | |||
| 664 | data = host->data; | ||
| 665 | host->data = NULL; | ||
| 666 | |||
| 667 | if (pcr->trans_result == TRANS_NO_DEVICE) | ||
| 668 | err = -ENODEV; | ||
| 669 | else if (pcr->trans_result != TRANS_RESULT_OK) | ||
| 670 | err = -EINVAL; | ||
| 671 | |||
| 672 | if (err < 0) { | ||
| 673 | data->error = err; | ||
| 674 | goto out; | ||
| 675 | } | ||
| 676 | |||
| 677 | if (!host->mrq->sbc && data->stop) { | ||
| 678 | sd_send_cmd(host, data->stop); | ||
| 679 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 680 | return; | ||
| 681 | } | ||
| 682 | |||
| 683 | out: | ||
| 684 | tasklet_schedule(&host->finish_tasklet); | ||
| 685 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 686 | } | ||
| 687 | |||
| 434 | static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host) | 688 | static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host) |
| 435 | { | 689 | { |
| 436 | rtsx_pci_write_register(host->pcr, SD_CFG1, | 690 | rtsx_pci_write_register(host->pcr, SD_CFG1, |
| @@ -511,85 +765,47 @@ static int sd_change_phase(struct realtek_pci_sdmmc *host, | |||
| 511 | return 0; | 765 | return 0; |
| 512 | } | 766 | } |
| 513 | 767 | ||
| 514 | static u8 sd_search_final_phase(struct realtek_pci_sdmmc *host, u32 phase_map) | 768 | static inline u32 test_phase_bit(u32 phase_map, unsigned int bit) |
| 515 | { | 769 | { |
| 516 | struct timing_phase_path path[MAX_PHASE + 1]; | 770 | bit %= RTSX_PHASE_MAX; |
| 517 | int i, j, cont_path_cnt; | 771 | return phase_map & (1 << bit); |
| 518 | int new_block, max_len, final_path_idx; | 772 | } |
| 519 | u8 final_phase = 0xFF; | ||
| 520 | 773 | ||
| 521 | /* Parse phase_map, take it as a bit-ring */ | 774 | static int sd_get_phase_len(u32 phase_map, unsigned int start_bit) |
| 522 | cont_path_cnt = 0; | 775 | { |
| 523 | new_block = 1; | 776 | int i; |
| 524 | j = 0; | ||
| 525 | for (i = 0; i < MAX_PHASE + 1; i++) { | ||
| 526 | if (phase_map & (1 << i)) { | ||
| 527 | if (new_block) { | ||
| 528 | new_block = 0; | ||
| 529 | j = cont_path_cnt++; | ||
| 530 | path[j].start = i; | ||
| 531 | path[j].end = i; | ||
| 532 | } else { | ||
| 533 | path[j].end = i; | ||
| 534 | } | ||
| 535 | } else { | ||
| 536 | new_block = 1; | ||
| 537 | if (cont_path_cnt) { | ||
| 538 | /* Calculate path length and middle point */ | ||
| 539 | int idx = cont_path_cnt - 1; | ||
| 540 | path[idx].len = | ||
| 541 | path[idx].end - path[idx].start + 1; | ||
| 542 | path[idx].mid = | ||
| 543 | path[idx].start + path[idx].len / 2; | ||
| 544 | } | ||
| 545 | } | ||
| 546 | } | ||
| 547 | 777 | ||
| 548 | if (cont_path_cnt == 0) { | 778 | for (i = 0; i < RTSX_PHASE_MAX; i++) { |
| 549 | dev_dbg(sdmmc_dev(host), "No continuous phase path\n"); | 779 | if (test_phase_bit(phase_map, start_bit + i) == 0) |
| 550 | goto finish; | 780 | return i; |
| 551 | } else { | ||
| 552 | /* Calculate last continuous path length and middle point */ | ||
| 553 | int idx = cont_path_cnt - 1; | ||
| 554 | path[idx].len = path[idx].end - path[idx].start + 1; | ||
| 555 | path[idx].mid = path[idx].start + path[idx].len / 2; | ||
| 556 | } | 781 | } |
| 782 | return RTSX_PHASE_MAX; | ||
| 783 | } | ||
| 784 | |||
| 785 | static u8 sd_search_final_phase(struct realtek_pci_sdmmc *host, u32 phase_map) | ||
| 786 | { | ||
| 787 | int start = 0, len = 0; | ||
| 788 | int start_final = 0, len_final = 0; | ||
| 789 | u8 final_phase = 0xFF; | ||
| 557 | 790 | ||
| 558 | /* Connect the first and last continuous paths if they are adjacent */ | 791 | if (phase_map == 0) { |
| 559 | if (!path[0].start && (path[cont_path_cnt - 1].end == MAX_PHASE)) { | 792 | dev_err(sdmmc_dev(host), "phase error: [map:%x]\n", phase_map); |
| 560 | /* Using negative index */ | 793 | return final_phase; |
| 561 | path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1; | ||
| 562 | path[0].len += path[cont_path_cnt - 1].len; | ||
| 563 | path[0].mid = path[0].start + path[0].len / 2; | ||
| 564 | /* Convert negative middle point index to positive one */ | ||
| 565 | if (path[0].mid < 0) | ||
| 566 | path[0].mid += MAX_PHASE + 1; | ||
| 567 | cont_path_cnt--; | ||
| 568 | } | 794 | } |
| 569 | 795 | ||
| 570 | /* Choose the longest continuous phase path */ | 796 | while (start < RTSX_PHASE_MAX) { |
| 571 | max_len = 0; | 797 | len = sd_get_phase_len(phase_map, start); |
| 572 | final_phase = 0; | 798 | if (len_final < len) { |
| 573 | final_path_idx = 0; | 799 | start_final = start; |
| 574 | for (i = 0; i < cont_path_cnt; i++) { | 800 | len_final = len; |
| 575 | if (path[i].len > max_len) { | ||
| 576 | max_len = path[i].len; | ||
| 577 | final_phase = (u8)path[i].mid; | ||
| 578 | final_path_idx = i; | ||
| 579 | } | 801 | } |
| 580 | 802 | start += len ? len : 1; | |
| 581 | dev_dbg(sdmmc_dev(host), "path[%d].start = %d\n", | ||
| 582 | i, path[i].start); | ||
| 583 | dev_dbg(sdmmc_dev(host), "path[%d].end = %d\n", | ||
| 584 | i, path[i].end); | ||
| 585 | dev_dbg(sdmmc_dev(host), "path[%d].len = %d\n", | ||
| 586 | i, path[i].len); | ||
| 587 | dev_dbg(sdmmc_dev(host), "path[%d].mid = %d\n", | ||
| 588 | i, path[i].mid); | ||
| 589 | } | 803 | } |
| 590 | 804 | ||
| 591 | finish: | 805 | final_phase = (start_final + len_final / 2) % RTSX_PHASE_MAX; |
| 592 | dev_dbg(sdmmc_dev(host), "Final chosen phase: %d\n", final_phase); | 806 | dev_dbg(sdmmc_dev(host), "phase: [map:%x] [maxlen:%d] [final:%d]\n", |
| 807 | phase_map, len_final, final_phase); | ||
| 808 | |||
| 593 | return final_phase; | 809 | return final_phase; |
| 594 | } | 810 | } |
| 595 | 811 | ||
| @@ -635,7 +851,7 @@ static int sd_tuning_phase(struct realtek_pci_sdmmc *host, | |||
| 635 | int err, i; | 851 | int err, i; |
| 636 | u32 raw_phase_map = 0; | 852 | u32 raw_phase_map = 0; |
| 637 | 853 | ||
| 638 | for (i = MAX_PHASE; i >= 0; i--) { | 854 | for (i = 0; i < RTSX_PHASE_MAX; i++) { |
| 639 | err = sd_tuning_rx_cmd(host, opcode, (u8)i); | 855 | err = sd_tuning_rx_cmd(host, opcode, (u8)i); |
| 640 | if (err == 0) | 856 | if (err == 0) |
| 641 | raw_phase_map |= 1 << i; | 857 | raw_phase_map |= 1 << i; |
| @@ -685,6 +901,13 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode) | |||
| 685 | return 0; | 901 | return 0; |
| 686 | } | 902 | } |
| 687 | 903 | ||
| 904 | static inline bool sd_use_muti_rw(struct mmc_command *cmd) | ||
| 905 | { | ||
| 906 | return mmc_op_multi(cmd->opcode) || | ||
| 907 | (cmd->opcode == MMC_READ_SINGLE_BLOCK) || | ||
| 908 | (cmd->opcode == MMC_WRITE_BLOCK); | ||
| 909 | } | ||
| 910 | |||
| 688 | static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | 911 | static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) |
| 689 | { | 912 | { |
| 690 | struct realtek_pci_sdmmc *host = mmc_priv(mmc); | 913 | struct realtek_pci_sdmmc *host = mmc_priv(mmc); |
| @@ -693,6 +916,14 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 693 | struct mmc_data *data = mrq->data; | 916 | struct mmc_data *data = mrq->data; |
| 694 | unsigned int data_size = 0; | 917 | unsigned int data_size = 0; |
| 695 | int err; | 918 | int err; |
| 919 | unsigned long flags; | ||
| 920 | |||
| 921 | mutex_lock(&pcr->pcr_mutex); | ||
| 922 | spin_lock_irqsave(&host->lock, flags); | ||
| 923 | |||
| 924 | if (host->mrq) | ||
| 925 | dev_err(sdmmc_dev(host), "error: request already exist\n"); | ||
| 926 | host->mrq = mrq; | ||
| 696 | 927 | ||
| 697 | if (host->eject) { | 928 | if (host->eject) { |
| 698 | cmd->error = -ENOMEDIUM; | 929 | cmd->error = -ENOMEDIUM; |
| @@ -705,8 +936,6 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 705 | goto finish; | 936 | goto finish; |
| 706 | } | 937 | } |
| 707 | 938 | ||
| 708 | mutex_lock(&pcr->pcr_mutex); | ||
| 709 | |||
| 710 | rtsx_pci_start_run(pcr); | 939 | rtsx_pci_start_run(pcr); |
| 711 | 940 | ||
| 712 | rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth, | 941 | rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth, |
| @@ -715,46 +944,28 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 715 | rtsx_pci_write_register(pcr, CARD_SHARE_MODE, | 944 | rtsx_pci_write_register(pcr, CARD_SHARE_MODE, |
| 716 | CARD_SHARE_MASK, CARD_SHARE_48_SD); | 945 | CARD_SHARE_MASK, CARD_SHARE_48_SD); |
| 717 | 946 | ||
| 718 | mutex_lock(&host->host_mutex); | ||
| 719 | host->mrq = mrq; | ||
| 720 | mutex_unlock(&host->host_mutex); | ||
| 721 | |||
| 722 | if (mrq->data) | 947 | if (mrq->data) |
| 723 | data_size = data->blocks * data->blksz; | 948 | data_size = data->blocks * data->blksz; |
| 724 | 949 | ||
| 725 | if (!data_size || mmc_op_multi(cmd->opcode) || | 950 | if (sd_use_muti_rw(cmd)) |
| 726 | (cmd->opcode == MMC_READ_SINGLE_BLOCK) || | 951 | host->sg_count = sd_pre_dma_transfer(host, data, NULL); |
| 727 | (cmd->opcode == MMC_WRITE_BLOCK)) { | ||
| 728 | sd_send_cmd_get_rsp(host, cmd); | ||
| 729 | |||
| 730 | if (!cmd->error && data_size) { | ||
| 731 | sd_rw_multi(host, mrq); | ||
| 732 | 952 | ||
| 733 | if (mmc_op_multi(cmd->opcode) && mrq->stop) | 953 | if (!data_size || sd_use_muti_rw(cmd)) { |
| 734 | sd_send_cmd_get_rsp(host, mrq->stop); | 954 | if (mrq->sbc) |
| 735 | } | 955 | sd_send_cmd(host, mrq->sbc); |
| 956 | else | ||
| 957 | sd_send_cmd(host, cmd); | ||
| 958 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 736 | } else { | 959 | } else { |
| 960 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 737 | sd_normal_rw(host, mrq); | 961 | sd_normal_rw(host, mrq); |
| 962 | tasklet_schedule(&host->finish_tasklet); | ||
| 738 | } | 963 | } |
| 739 | 964 | return; | |
| 740 | if (mrq->data) { | ||
| 741 | if (cmd->error || data->error) | ||
| 742 | data->bytes_xfered = 0; | ||
| 743 | else | ||
| 744 | data->bytes_xfered = data->blocks * data->blksz; | ||
| 745 | } | ||
| 746 | |||
| 747 | mutex_unlock(&pcr->pcr_mutex); | ||
| 748 | 965 | ||
| 749 | finish: | 966 | finish: |
| 750 | if (cmd->error) | 967 | tasklet_schedule(&host->finish_tasklet); |
| 751 | dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); | 968 | spin_unlock_irqrestore(&host->lock, flags); |
| 752 | |||
| 753 | mutex_lock(&host->host_mutex); | ||
| 754 | host->mrq = NULL; | ||
| 755 | mutex_unlock(&host->host_mutex); | ||
| 756 | |||
| 757 | mmc_request_done(mmc, mrq); | ||
| 758 | } | 969 | } |
| 759 | 970 | ||
| 760 | static int sd_set_bus_width(struct realtek_pci_sdmmc *host, | 971 | static int sd_set_bus_width(struct realtek_pci_sdmmc *host, |
| @@ -1189,6 +1400,8 @@ out: | |||
| 1189 | } | 1400 | } |
| 1190 | 1401 | ||
| 1191 | static const struct mmc_host_ops realtek_pci_sdmmc_ops = { | 1402 | static const struct mmc_host_ops realtek_pci_sdmmc_ops = { |
| 1403 | .pre_req = sdmmc_pre_req, | ||
| 1404 | .post_req = sdmmc_post_req, | ||
| 1192 | .request = sdmmc_request, | 1405 | .request = sdmmc_request, |
| 1193 | .set_ios = sdmmc_set_ios, | 1406 | .set_ios = sdmmc_set_ios, |
| 1194 | .get_ro = sdmmc_get_ro, | 1407 | .get_ro = sdmmc_get_ro, |
| @@ -1252,6 +1465,7 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) | |||
| 1252 | struct realtek_pci_sdmmc *host; | 1465 | struct realtek_pci_sdmmc *host; |
| 1253 | struct rtsx_pcr *pcr; | 1466 | struct rtsx_pcr *pcr; |
| 1254 | struct pcr_handle *handle = pdev->dev.platform_data; | 1467 | struct pcr_handle *handle = pdev->dev.platform_data; |
| 1468 | unsigned long host_addr; | ||
| 1255 | 1469 | ||
| 1256 | if (!handle) | 1470 | if (!handle) |
| 1257 | return -ENXIO; | 1471 | return -ENXIO; |
| @@ -1275,8 +1489,15 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) | |||
| 1275 | pcr->slots[RTSX_SD_CARD].p_dev = pdev; | 1489 | pcr->slots[RTSX_SD_CARD].p_dev = pdev; |
| 1276 | pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; | 1490 | pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; |
| 1277 | 1491 | ||
| 1278 | mutex_init(&host->host_mutex); | 1492 | host_addr = (unsigned long)host; |
| 1493 | host->next_data.cookie = 1; | ||
| 1494 | setup_timer(&host->timer, sd_request_timeout, host_addr); | ||
| 1495 | tasklet_init(&host->cmd_tasklet, sd_get_rsp, host_addr); | ||
| 1496 | tasklet_init(&host->data_tasklet, sd_finish_multi_rw, host_addr); | ||
| 1497 | tasklet_init(&host->finish_tasklet, sd_finish_request, host_addr); | ||
| 1498 | spin_lock_init(&host->lock); | ||
| 1279 | 1499 | ||
| 1500 | pcr->slots[RTSX_SD_CARD].done_transfer = sd_isr_done_transfer; | ||
| 1280 | realtek_init_host(host); | 1501 | realtek_init_host(host); |
| 1281 | 1502 | ||
| 1282 | mmc_add_host(mmc); | 1503 | mmc_add_host(mmc); |
| @@ -1289,6 +1510,8 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) | |||
| 1289 | struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); | 1510 | struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); |
| 1290 | struct rtsx_pcr *pcr; | 1511 | struct rtsx_pcr *pcr; |
| 1291 | struct mmc_host *mmc; | 1512 | struct mmc_host *mmc; |
| 1513 | struct mmc_request *mrq; | ||
| 1514 | unsigned long flags; | ||
| 1292 | 1515 | ||
| 1293 | if (!host) | 1516 | if (!host) |
| 1294 | return 0; | 1517 | return 0; |
| @@ -1296,25 +1519,37 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) | |||
| 1296 | pcr = host->pcr; | 1519 | pcr = host->pcr; |
| 1297 | pcr->slots[RTSX_SD_CARD].p_dev = NULL; | 1520 | pcr->slots[RTSX_SD_CARD].p_dev = NULL; |
| 1298 | pcr->slots[RTSX_SD_CARD].card_event = NULL; | 1521 | pcr->slots[RTSX_SD_CARD].card_event = NULL; |
| 1522 | pcr->slots[RTSX_SD_CARD].done_transfer = NULL; | ||
| 1299 | mmc = host->mmc; | 1523 | mmc = host->mmc; |
| 1300 | host->eject = true; | 1524 | mrq = host->mrq; |
| 1301 | 1525 | ||
| 1302 | mutex_lock(&host->host_mutex); | 1526 | spin_lock_irqsave(&host->lock, flags); |
| 1303 | if (host->mrq) { | 1527 | if (host->mrq) { |
| 1304 | dev_dbg(&(pdev->dev), | 1528 | dev_dbg(&(pdev->dev), |
| 1305 | "%s: Controller removed during transfer\n", | 1529 | "%s: Controller removed during transfer\n", |
| 1306 | mmc_hostname(mmc)); | 1530 | mmc_hostname(mmc)); |
| 1307 | 1531 | ||
| 1308 | rtsx_pci_complete_unfinished_transfer(pcr); | 1532 | if (mrq->sbc) |
| 1533 | mrq->sbc->error = -ENOMEDIUM; | ||
| 1534 | if (mrq->cmd) | ||
| 1535 | mrq->cmd->error = -ENOMEDIUM; | ||
| 1536 | if (mrq->stop) | ||
| 1537 | mrq->stop->error = -ENOMEDIUM; | ||
| 1538 | if (mrq->data) | ||
| 1539 | mrq->data->error = -ENOMEDIUM; | ||
| 1309 | 1540 | ||
| 1310 | host->mrq->cmd->error = -ENOMEDIUM; | 1541 | tasklet_schedule(&host->finish_tasklet); |
| 1311 | if (host->mrq->stop) | ||
| 1312 | host->mrq->stop->error = -ENOMEDIUM; | ||
| 1313 | mmc_request_done(mmc, host->mrq); | ||
| 1314 | } | 1542 | } |
| 1315 | mutex_unlock(&host->host_mutex); | 1543 | spin_unlock_irqrestore(&host->lock, flags); |
| 1544 | |||
| 1545 | del_timer_sync(&host->timer); | ||
| 1546 | tasklet_kill(&host->cmd_tasklet); | ||
| 1547 | tasklet_kill(&host->data_tasklet); | ||
| 1548 | tasklet_kill(&host->finish_tasklet); | ||
| 1316 | 1549 | ||
| 1317 | mmc_remove_host(mmc); | 1550 | mmc_remove_host(mmc); |
| 1551 | host->eject = true; | ||
| 1552 | |||
| 1318 | mmc_free_host(mmc); | 1553 | mmc_free_host(mmc); |
| 1319 | 1554 | ||
| 1320 | dev_dbg(&(pdev->dev), | 1555 | dev_dbg(&(pdev->dev), |
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 9ce17f6e4014..ebb3f392b589 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | #include <linux/bitops.h> | 31 | #include <linux/bitops.h> |
| 32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
| 33 | #include <linux/err.h> | 33 | #include <linux/err.h> |
| 34 | #include <linux/gpio/consumer.h> | ||
| 35 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
| 36 | #include <linux/acpi.h> | 35 | #include <linux/acpi.h> |
| 37 | #include <linux/pm.h> | 36 | #include <linux/pm.h> |
| @@ -40,13 +39,15 @@ | |||
| 40 | 39 | ||
| 41 | #include <linux/mmc/host.h> | 40 | #include <linux/mmc/host.h> |
| 42 | #include <linux/mmc/pm.h> | 41 | #include <linux/mmc/pm.h> |
| 42 | #include <linux/mmc/slot-gpio.h> | ||
| 43 | #include <linux/mmc/sdhci.h> | 43 | #include <linux/mmc/sdhci.h> |
| 44 | 44 | ||
| 45 | #include "sdhci.h" | 45 | #include "sdhci.h" |
| 46 | 46 | ||
| 47 | enum { | 47 | enum { |
| 48 | SDHCI_ACPI_SD_CD = BIT(0), | 48 | SDHCI_ACPI_SD_CD = BIT(0), |
| 49 | SDHCI_ACPI_RUNTIME_PM = BIT(1), | 49 | SDHCI_ACPI_RUNTIME_PM = BIT(1), |
| 50 | SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL = BIT(2), | ||
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | struct sdhci_acpi_chip { | 53 | struct sdhci_acpi_chip { |
| @@ -121,6 +122,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = { | |||
| 121 | }; | 122 | }; |
| 122 | 123 | ||
| 123 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { | 124 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { |
| 125 | .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION, | ||
| 124 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON, | 126 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON, |
| 125 | .caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD, | 127 | .caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD, |
| 126 | .flags = SDHCI_ACPI_RUNTIME_PM, | 128 | .flags = SDHCI_ACPI_RUNTIME_PM, |
| @@ -128,7 +130,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { | |||
| 128 | }; | 130 | }; |
| 129 | 131 | ||
| 130 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { | 132 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { |
| 131 | .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_RUNTIME_PM, | 133 | .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL | |
| 134 | SDHCI_ACPI_RUNTIME_PM, | ||
| 132 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, | 135 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, |
| 133 | }; | 136 | }; |
| 134 | 137 | ||
| @@ -141,6 +144,7 @@ struct sdhci_acpi_uid_slot { | |||
| 141 | static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = { | 144 | static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = { |
| 142 | { "80860F14" , "1" , &sdhci_acpi_slot_int_emmc }, | 145 | { "80860F14" , "1" , &sdhci_acpi_slot_int_emmc }, |
| 143 | { "80860F14" , "3" , &sdhci_acpi_slot_int_sd }, | 146 | { "80860F14" , "3" , &sdhci_acpi_slot_int_sd }, |
| 147 | { "80860F16" , NULL, &sdhci_acpi_slot_int_sd }, | ||
| 144 | { "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio }, | 148 | { "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio }, |
| 145 | { "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio }, | 149 | { "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio }, |
| 146 | { "INT3436" , NULL, &sdhci_acpi_slot_int_sdio }, | 150 | { "INT3436" , NULL, &sdhci_acpi_slot_int_sdio }, |
| @@ -150,6 +154,7 @@ static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = { | |||
| 150 | 154 | ||
| 151 | static const struct acpi_device_id sdhci_acpi_ids[] = { | 155 | static const struct acpi_device_id sdhci_acpi_ids[] = { |
| 152 | { "80860F14" }, | 156 | { "80860F14" }, |
| 157 | { "80860F16" }, | ||
| 153 | { "INT33BB" }, | 158 | { "INT33BB" }, |
| 154 | { "INT33C6" }, | 159 | { "INT33C6" }, |
| 155 | { "INT3436" }, | 160 | { "INT3436" }, |
| @@ -192,59 +197,6 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(acpi_handle handle, | |||
| 192 | return slot; | 197 | return slot; |
| 193 | } | 198 | } |
| 194 | 199 | ||
| 195 | #ifdef CONFIG_PM_RUNTIME | ||
| 196 | |||
| 197 | static irqreturn_t sdhci_acpi_sd_cd(int irq, void *dev_id) | ||
| 198 | { | ||
| 199 | mmc_detect_change(dev_id, msecs_to_jiffies(200)); | ||
| 200 | return IRQ_HANDLED; | ||
| 201 | } | ||
| 202 | |||
| 203 | static int sdhci_acpi_add_own_cd(struct device *dev, struct mmc_host *mmc) | ||
| 204 | { | ||
| 205 | struct gpio_desc *desc; | ||
| 206 | unsigned long flags; | ||
| 207 | int err, irq; | ||
| 208 | |||
| 209 | desc = devm_gpiod_get_index(dev, "sd_cd", 0); | ||
| 210 | if (IS_ERR(desc)) { | ||
| 211 | err = PTR_ERR(desc); | ||
| 212 | goto out; | ||
| 213 | } | ||
| 214 | |||
| 215 | err = gpiod_direction_input(desc); | ||
| 216 | if (err) | ||
| 217 | goto out_free; | ||
| 218 | |||
| 219 | irq = gpiod_to_irq(desc); | ||
| 220 | if (irq < 0) { | ||
| 221 | err = irq; | ||
| 222 | goto out_free; | ||
| 223 | } | ||
| 224 | |||
| 225 | flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; | ||
| 226 | err = devm_request_irq(dev, irq, sdhci_acpi_sd_cd, flags, "sd_cd", mmc); | ||
| 227 | if (err) | ||
| 228 | goto out_free; | ||
| 229 | |||
| 230 | return 0; | ||
| 231 | |||
| 232 | out_free: | ||
| 233 | devm_gpiod_put(dev, desc); | ||
| 234 | out: | ||
| 235 | dev_warn(dev, "failed to setup card detect wake up\n"); | ||
| 236 | return err; | ||
| 237 | } | ||
| 238 | |||
| 239 | #else | ||
| 240 | |||
| 241 | static int sdhci_acpi_add_own_cd(struct device *dev, struct mmc_host *mmc) | ||
| 242 | { | ||
| 243 | return 0; | ||
| 244 | } | ||
| 245 | |||
| 246 | #endif | ||
| 247 | |||
| 248 | static int sdhci_acpi_probe(struct platform_device *pdev) | 200 | static int sdhci_acpi_probe(struct platform_device *pdev) |
| 249 | { | 201 | { |
| 250 | struct device *dev = &pdev->dev; | 202 | struct device *dev = &pdev->dev; |
| @@ -332,15 +284,19 @@ static int sdhci_acpi_probe(struct platform_device *pdev) | |||
| 332 | 284 | ||
| 333 | host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; | 285 | host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; |
| 334 | 286 | ||
| 335 | err = sdhci_add_host(host); | ||
| 336 | if (err) | ||
| 337 | goto err_free; | ||
| 338 | |||
| 339 | if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { | 287 | if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { |
| 340 | if (sdhci_acpi_add_own_cd(dev, host->mmc)) | 288 | bool v = sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL); |
| 289 | |||
| 290 | if (mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0)) { | ||
| 291 | dev_warn(dev, "failed to setup card detect gpio\n"); | ||
| 341 | c->use_runtime_pm = false; | 292 | c->use_runtime_pm = false; |
| 293 | } | ||
| 342 | } | 294 | } |
| 343 | 295 | ||
| 296 | err = sdhci_add_host(host); | ||
| 297 | if (err) | ||
| 298 | goto err_free; | ||
| 299 | |||
| 344 | if (c->use_runtime_pm) { | 300 | if (c->use_runtime_pm) { |
| 345 | pm_runtime_set_active(dev); | 301 | pm_runtime_set_active(dev); |
| 346 | pm_suspend_ignore_children(dev, 1); | 302 | pm_suspend_ignore_children(dev, 1); |
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index 7a190fe4dff1..6f166e63b817 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | 54 | ||
| 55 | struct sdhci_bcm_kona_dev { | 55 | struct sdhci_bcm_kona_dev { |
| 56 | struct mutex write_lock; /* protect back to back writes */ | 56 | struct mutex write_lock; /* protect back to back writes */ |
| 57 | struct clk *external_clk; | ||
| 57 | }; | 58 | }; |
| 58 | 59 | ||
| 59 | 60 | ||
| @@ -257,6 +258,24 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev) | |||
| 257 | goto err_pltfm_free; | 258 | goto err_pltfm_free; |
| 258 | } | 259 | } |
| 259 | 260 | ||
| 261 | /* Get and enable the external clock */ | ||
| 262 | kona_dev->external_clk = devm_clk_get(dev, NULL); | ||
| 263 | if (IS_ERR(kona_dev->external_clk)) { | ||
| 264 | dev_err(dev, "Failed to get external clock\n"); | ||
| 265 | ret = PTR_ERR(kona_dev->external_clk); | ||
| 266 | goto err_pltfm_free; | ||
| 267 | } | ||
| 268 | |||
| 269 | if (clk_set_rate(kona_dev->external_clk, host->mmc->f_max) != 0) { | ||
| 270 | dev_err(dev, "Failed to set rate external clock\n"); | ||
| 271 | goto err_pltfm_free; | ||
| 272 | } | ||
| 273 | |||
| 274 | if (clk_prepare_enable(kona_dev->external_clk) != 0) { | ||
| 275 | dev_err(dev, "Failed to enable external clock\n"); | ||
| 276 | goto err_pltfm_free; | ||
| 277 | } | ||
| 278 | |||
| 260 | dev_dbg(dev, "non-removable=%c\n", | 279 | dev_dbg(dev, "non-removable=%c\n", |
| 261 | (host->mmc->caps & MMC_CAP_NONREMOVABLE) ? 'Y' : 'N'); | 280 | (host->mmc->caps & MMC_CAP_NONREMOVABLE) ? 'Y' : 'N'); |
| 262 | dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n", | 281 | dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n", |
| @@ -271,7 +290,7 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev) | |||
| 271 | 290 | ||
| 272 | ret = sdhci_bcm_kona_sd_reset(host); | 291 | ret = sdhci_bcm_kona_sd_reset(host); |
| 273 | if (ret) | 292 | if (ret) |
| 274 | goto err_pltfm_free; | 293 | goto err_clk_disable; |
| 275 | 294 | ||
| 276 | sdhci_bcm_kona_sd_init(host); | 295 | sdhci_bcm_kona_sd_init(host); |
| 277 | 296 | ||
| @@ -307,6 +326,9 @@ err_remove_host: | |||
| 307 | err_reset: | 326 | err_reset: |
| 308 | sdhci_bcm_kona_sd_reset(host); | 327 | sdhci_bcm_kona_sd_reset(host); |
| 309 | 328 | ||
| 329 | err_clk_disable: | ||
| 330 | clk_disable_unprepare(kona_dev->external_clk); | ||
| 331 | |||
| 310 | err_pltfm_free: | 332 | err_pltfm_free: |
| 311 | sdhci_pltfm_free(pdev); | 333 | sdhci_pltfm_free(pdev); |
| 312 | 334 | ||
| @@ -314,9 +336,20 @@ err_pltfm_free: | |||
| 314 | return ret; | 336 | return ret; |
| 315 | } | 337 | } |
| 316 | 338 | ||
| 317 | static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev) | 339 | static int sdhci_bcm_kona_remove(struct platform_device *pdev) |
| 318 | { | 340 | { |
| 319 | return sdhci_pltfm_unregister(pdev); | 341 | struct sdhci_host *host = platform_get_drvdata(pdev); |
| 342 | struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); | ||
| 343 | struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv); | ||
| 344 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); | ||
| 345 | |||
| 346 | sdhci_remove_host(host, dead); | ||
| 347 | |||
| 348 | clk_disable_unprepare(kona_dev->external_clk); | ||
| 349 | |||
| 350 | sdhci_pltfm_free(pdev); | ||
| 351 | |||
| 352 | return 0; | ||
| 320 | } | 353 | } |
| 321 | 354 | ||
| 322 | static struct platform_driver sdhci_bcm_kona_driver = { | 355 | static struct platform_driver sdhci_bcm_kona_driver = { |
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 8424839660f8..736d7a2eb7ec 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c | |||
| @@ -208,7 +208,7 @@ static struct platform_driver sdhci_dove_driver = { | |||
| 208 | .name = "sdhci-dove", | 208 | .name = "sdhci-dove", |
| 209 | .owner = THIS_MODULE, | 209 | .owner = THIS_MODULE, |
| 210 | .pm = SDHCI_PLTFM_PMOPS, | 210 | .pm = SDHCI_PLTFM_PMOPS, |
| 211 | .of_match_table = of_match_ptr(sdhci_dove_of_match_table), | 211 | .of_match_table = sdhci_dove_of_match_table, |
| 212 | }, | 212 | }, |
| 213 | .probe = sdhci_dove_probe, | 213 | .probe = sdhci_dove_probe, |
| 214 | .remove = sdhci_dove_remove, | 214 | .remove = sdhci_dove_remove, |
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c new file mode 100644 index 000000000000..acb0e9eb55f1 --- /dev/null +++ b/drivers/mmc/host/sdhci-msm.c | |||
| @@ -0,0 +1,618 @@ | |||
| 1 | /* | ||
| 2 | * drivers/mmc/host/sdhci-msm.c - Qualcomm SDHCI Platform driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 and | ||
| 8 | * only version 2 as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/of_device.h> | ||
| 19 | #include <linux/regulator/consumer.h> | ||
| 20 | #include <linux/delay.h> | ||
| 21 | #include <linux/mmc/mmc.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | |||
| 24 | #include "sdhci-pltfm.h" | ||
| 25 | |||
| 26 | #define CORE_HC_MODE 0x78 | ||
| 27 | #define HC_MODE_EN 0x1 | ||
| 28 | #define CORE_POWER 0x0 | ||
| 29 | #define CORE_SW_RST BIT(7) | ||
| 30 | |||
| 31 | #define MAX_PHASES 16 | ||
| 32 | #define CORE_DLL_LOCK BIT(7) | ||
| 33 | #define CORE_DLL_EN BIT(16) | ||
| 34 | #define CORE_CDR_EN BIT(17) | ||
| 35 | #define CORE_CK_OUT_EN BIT(18) | ||
| 36 | #define CORE_CDR_EXT_EN BIT(19) | ||
| 37 | #define CORE_DLL_PDN BIT(29) | ||
| 38 | #define CORE_DLL_RST BIT(30) | ||
| 39 | #define CORE_DLL_CONFIG 0x100 | ||
| 40 | #define CORE_DLL_STATUS 0x108 | ||
| 41 | |||
| 42 | #define CORE_VENDOR_SPEC 0x10c | ||
| 43 | #define CORE_CLK_PWRSAVE BIT(1) | ||
| 44 | |||
| 45 | #define CDR_SELEXT_SHIFT 20 | ||
| 46 | #define CDR_SELEXT_MASK (0xf << CDR_SELEXT_SHIFT) | ||
| 47 | #define CMUX_SHIFT_PHASE_SHIFT 24 | ||
| 48 | #define CMUX_SHIFT_PHASE_MASK (7 << CMUX_SHIFT_PHASE_SHIFT) | ||
| 49 | |||
| 50 | static const u32 tuning_block_64[] = { | ||
| 51 | 0x00ff0fff, 0xccc3ccff, 0xffcc3cc3, 0xeffefffe, | ||
| 52 | 0xddffdfff, 0xfbfffbff, 0xff7fffbf, 0xefbdf777, | ||
| 53 | 0xf0fff0ff, 0x3cccfc0f, 0xcfcc33cc, 0xeeffefff, | ||
| 54 | 0xfdfffdff, 0xffbfffdf, 0xfff7ffbb, 0xde7b7ff7 | ||
| 55 | }; | ||
| 56 | |||
| 57 | static const u32 tuning_block_128[] = { | ||
| 58 | 0xff00ffff, 0x0000ffff, 0xccccffff, 0xcccc33cc, | ||
| 59 | 0xcc3333cc, 0xffffcccc, 0xffffeeff, 0xffeeeeff, | ||
| 60 | 0xffddffff, 0xddddffff, 0xbbffffff, 0xbbffffff, | ||
| 61 | 0xffffffbb, 0xffffff77, 0x77ff7777, 0xffeeddbb, | ||
| 62 | 0x00ffffff, 0x00ffffff, 0xccffff00, 0xcc33cccc, | ||
| 63 | 0x3333cccc, 0xffcccccc, 0xffeeffff, 0xeeeeffff, | ||
| 64 | 0xddffffff, 0xddffffff, 0xffffffdd, 0xffffffbb, | ||
| 65 | 0xffffbbbb, 0xffff77ff, 0xff7777ff, 0xeeddbb77 | ||
| 66 | }; | ||
| 67 | |||
| 68 | struct sdhci_msm_host { | ||
| 69 | struct platform_device *pdev; | ||
| 70 | void __iomem *core_mem; /* MSM SDCC mapped address */ | ||
| 71 | struct clk *clk; /* main SD/MMC bus clock */ | ||
| 72 | struct clk *pclk; /* SDHC peripheral bus clock */ | ||
| 73 | struct clk *bus_clk; /* SDHC bus voter clock */ | ||
| 74 | struct mmc_host *mmc; | ||
| 75 | struct sdhci_pltfm_data sdhci_msm_pdata; | ||
| 76 | }; | ||
| 77 | |||
| 78 | /* Platform specific tuning */ | ||
| 79 | static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll) | ||
| 80 | { | ||
| 81 | u32 wait_cnt = 50; | ||
| 82 | u8 ck_out_en; | ||
| 83 | struct mmc_host *mmc = host->mmc; | ||
| 84 | |||
| 85 | /* Poll for CK_OUT_EN bit. max. poll time = 50us */ | ||
| 86 | ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) & | ||
| 87 | CORE_CK_OUT_EN); | ||
| 88 | |||
| 89 | while (ck_out_en != poll) { | ||
| 90 | if (--wait_cnt == 0) { | ||
| 91 | dev_err(mmc_dev(mmc), "%s: CK_OUT_EN bit is not %d\n", | ||
| 92 | mmc_hostname(mmc), poll); | ||
| 93 | return -ETIMEDOUT; | ||
| 94 | } | ||
| 95 | udelay(1); | ||
| 96 | |||
| 97 | ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) & | ||
| 98 | CORE_CK_OUT_EN); | ||
| 99 | } | ||
| 100 | |||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase) | ||
| 105 | { | ||
| 106 | int rc; | ||
| 107 | static const u8 grey_coded_phase_table[] = { | ||
| 108 | 0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4, | ||
| 109 | 0xc, 0xd, 0xf, 0xe, 0xa, 0xb, 0x9, 0x8 | ||
| 110 | }; | ||
| 111 | unsigned long flags; | ||
| 112 | u32 config; | ||
| 113 | struct mmc_host *mmc = host->mmc; | ||
| 114 | |||
| 115 | spin_lock_irqsave(&host->lock, flags); | ||
| 116 | |||
| 117 | config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); | ||
| 118 | config &= ~(CORE_CDR_EN | CORE_CK_OUT_EN); | ||
| 119 | config |= (CORE_CDR_EXT_EN | CORE_DLL_EN); | ||
| 120 | writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); | ||
| 121 | |||
| 122 | /* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '0' */ | ||
| 123 | rc = msm_dll_poll_ck_out_en(host, 0); | ||
| 124 | if (rc) | ||
| 125 | goto err_out; | ||
| 126 | |||
| 127 | /* | ||
| 128 | * Write the selected DLL clock output phase (0 ... 15) | ||
| 129 | * to CDR_SELEXT bit field of DLL_CONFIG register. | ||
| 130 | */ | ||
| 131 | config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); | ||
| 132 | config &= ~CDR_SELEXT_MASK; | ||
| 133 | config |= grey_coded_phase_table[phase] << CDR_SELEXT_SHIFT; | ||
| 134 | writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); | ||
| 135 | |||
| 136 | /* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */ | ||
| 137 | writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) | ||
| 138 | | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG); | ||
| 139 | |||
| 140 | /* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */ | ||
| 141 | rc = msm_dll_poll_ck_out_en(host, 1); | ||
| 142 | if (rc) | ||
| 143 | goto err_out; | ||
| 144 | |||
| 145 | config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); | ||
| 146 | config |= CORE_CDR_EN; | ||
| 147 | config &= ~CORE_CDR_EXT_EN; | ||
| 148 | writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); | ||
| 149 | goto out; | ||
| 150 | |||
| 151 | err_out: | ||
| 152 | dev_err(mmc_dev(mmc), "%s: Failed to set DLL phase: %d\n", | ||
| 153 | mmc_hostname(mmc), phase); | ||
| 154 | out: | ||
| 155 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 156 | return rc; | ||
| 157 | } | ||
| 158 | |||
| 159 | /* | ||
| 160 | * Find out the greatest range of consecuitive selected | ||
| 161 | * DLL clock output phases that can be used as sampling | ||
| 162 | * setting for SD3.0 UHS-I card read operation (in SDR104 | ||
| 163 | * timing mode) or for eMMC4.5 card read operation (in HS200 | ||
| 164 | * timing mode). | ||
| 165 | * Select the 3/4 of the range and configure the DLL with the | ||
| 166 | * selected DLL clock output phase. | ||
| 167 | */ | ||
| 168 | |||
| 169 | static int msm_find_most_appropriate_phase(struct sdhci_host *host, | ||
| 170 | u8 *phase_table, u8 total_phases) | ||
| 171 | { | ||
| 172 | int ret; | ||
| 173 | u8 ranges[MAX_PHASES][MAX_PHASES] = { {0}, {0} }; | ||
| 174 | u8 phases_per_row[MAX_PHASES] = { 0 }; | ||
| 175 | int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0; | ||
| 176 | int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0; | ||
| 177 | bool phase_0_found = false, phase_15_found = false; | ||
| 178 | struct mmc_host *mmc = host->mmc; | ||
| 179 | |||
| 180 | if (!total_phases || (total_phases > MAX_PHASES)) { | ||
| 181 | dev_err(mmc_dev(mmc), "%s: Invalid argument: total_phases=%d\n", | ||
| 182 | mmc_hostname(mmc), total_phases); | ||
| 183 | return -EINVAL; | ||
| 184 | } | ||
| 185 | |||
| 186 | for (cnt = 0; cnt < total_phases; cnt++) { | ||
| 187 | ranges[row_index][col_index] = phase_table[cnt]; | ||
| 188 | phases_per_row[row_index] += 1; | ||
| 189 | col_index++; | ||
| 190 | |||
| 191 | if ((cnt + 1) == total_phases) { | ||
| 192 | continue; | ||
| 193 | /* check if next phase in phase_table is consecutive or not */ | ||
| 194 | } else if ((phase_table[cnt] + 1) != phase_table[cnt + 1]) { | ||
| 195 | row_index++; | ||
| 196 | col_index = 0; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | if (row_index >= MAX_PHASES) | ||
| 201 | return -EINVAL; | ||
| 202 | |||
| 203 | /* Check if phase-0 is present in first valid window? */ | ||
| 204 | if (!ranges[0][0]) { | ||
| 205 | phase_0_found = true; | ||
| 206 | phase_0_raw_index = 0; | ||
| 207 | /* Check if cycle exist between 2 valid windows */ | ||
| 208 | for (cnt = 1; cnt <= row_index; cnt++) { | ||
| 209 | if (phases_per_row[cnt]) { | ||
| 210 | for (i = 0; i < phases_per_row[cnt]; i++) { | ||
| 211 | if (ranges[cnt][i] == 15) { | ||
| 212 | phase_15_found = true; | ||
| 213 | phase_15_raw_index = cnt; | ||
| 214 | break; | ||
| 215 | } | ||
| 216 | } | ||
| 217 | } | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | /* If 2 valid windows form cycle then merge them as single window */ | ||
| 222 | if (phase_0_found && phase_15_found) { | ||
| 223 | /* number of phases in raw where phase 0 is present */ | ||
| 224 | u8 phases_0 = phases_per_row[phase_0_raw_index]; | ||
| 225 | /* number of phases in raw where phase 15 is present */ | ||
| 226 | u8 phases_15 = phases_per_row[phase_15_raw_index]; | ||
| 227 | |||
| 228 | if (phases_0 + phases_15 >= MAX_PHASES) | ||
| 229 | /* | ||
| 230 | * If there are more than 1 phase windows then total | ||
| 231 | * number of phases in both the windows should not be | ||
| 232 | * more than or equal to MAX_PHASES. | ||
| 233 | */ | ||
| 234 | return -EINVAL; | ||
| 235 | |||
| 236 | /* Merge 2 cyclic windows */ | ||
| 237 | i = phases_15; | ||
| 238 | for (cnt = 0; cnt < phases_0; cnt++) { | ||
| 239 | ranges[phase_15_raw_index][i] = | ||
| 240 | ranges[phase_0_raw_index][cnt]; | ||
| 241 | if (++i >= MAX_PHASES) | ||
| 242 | break; | ||
| 243 | } | ||
| 244 | |||
| 245 | phases_per_row[phase_0_raw_index] = 0; | ||
| 246 | phases_per_row[phase_15_raw_index] = phases_15 + phases_0; | ||
| 247 | } | ||
| 248 | |||
| 249 | for (cnt = 0; cnt <= row_index; cnt++) { | ||
| 250 | if (phases_per_row[cnt] > curr_max) { | ||
| 251 | curr_max = phases_per_row[cnt]; | ||
| 252 | selected_row_index = cnt; | ||
| 253 | } | ||
| 254 | } | ||
| 255 | |||
| 256 | i = (curr_max * 3) / 4; | ||
| 257 | if (i) | ||
| 258 | i--; | ||
| 259 | |||
| 260 | ret = ranges[selected_row_index][i]; | ||
| 261 | |||
| 262 | if (ret >= MAX_PHASES) { | ||
| 263 | ret = -EINVAL; | ||
| 264 | dev_err(mmc_dev(mmc), "%s: Invalid phase selected=%d\n", | ||
| 265 | mmc_hostname(mmc), ret); | ||
| 266 | } | ||
| 267 | |||
| 268 | return ret; | ||
| 269 | } | ||
| 270 | |||
| 271 | static inline void msm_cm_dll_set_freq(struct sdhci_host *host) | ||
| 272 | { | ||
| 273 | u32 mclk_freq = 0, config; | ||
| 274 | |||
| 275 | /* Program the MCLK value to MCLK_FREQ bit field */ | ||
| 276 | if (host->clock <= 112000000) | ||
| 277 | mclk_freq = 0; | ||
| 278 | else if (host->clock <= 125000000) | ||
| 279 | mclk_freq = 1; | ||
| 280 | else if (host->clock <= 137000000) | ||
| 281 | mclk_freq = 2; | ||
| 282 | else if (host->clock <= 150000000) | ||
| 283 | mclk_freq = 3; | ||
| 284 | else if (host->clock <= 162000000) | ||
| 285 | mclk_freq = 4; | ||
| 286 | else if (host->clock <= 175000000) | ||
| 287 | mclk_freq = 5; | ||
| 288 | else if (host->clock <= 187000000) | ||
| 289 | mclk_freq = 6; | ||
| 290 | else if (host->clock <= 200000000) | ||
| 291 | mclk_freq = 7; | ||
| 292 | |||
| 293 | config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); | ||
| 294 | config &= ~CMUX_SHIFT_PHASE_MASK; | ||
| 295 | config |= mclk_freq << CMUX_SHIFT_PHASE_SHIFT; | ||
| 296 | writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); | ||
| 297 | } | ||
| 298 | |||
| 299 | /* Initialize the DLL (Programmable Delay Line) */ | ||
| 300 | static int msm_init_cm_dll(struct sdhci_host *host) | ||
| 301 | { | ||
| 302 | struct mmc_host *mmc = host->mmc; | ||
| 303 | int wait_cnt = 50; | ||
| 304 | unsigned long flags; | ||
| 305 | |||
| 306 | spin_lock_irqsave(&host->lock, flags); | ||
| 307 | |||
| 308 | /* | ||
| 309 | * Make sure that clock is always enabled when DLL | ||
| 310 | * tuning is in progress. Keeping PWRSAVE ON may | ||
| 311 | * turn off the clock. | ||
| 312 | */ | ||
| 313 | writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) | ||
| 314 | & ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC); | ||
| 315 | |||
| 316 | /* Write 1 to DLL_RST bit of DLL_CONFIG register */ | ||
| 317 | writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) | ||
| 318 | | CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG); | ||
| 319 | |||
| 320 | /* Write 1 to DLL_PDN bit of DLL_CONFIG register */ | ||
| 321 | writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) | ||
| 322 | | CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG); | ||
| 323 | msm_cm_dll_set_freq(host); | ||
| 324 | |||
| 325 | /* Write 0 to DLL_RST bit of DLL_CONFIG register */ | ||
| 326 | writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) | ||
| 327 | & ~CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG); | ||
| 328 | |||
| 329 | /* Write 0 to DLL_PDN bit of DLL_CONFIG register */ | ||
| 330 | writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) | ||
| 331 | & ~CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG); | ||
| 332 | |||
| 333 | /* Set DLL_EN bit to 1. */ | ||
| 334 | writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) | ||
| 335 | | CORE_DLL_EN), host->ioaddr + CORE_DLL_CONFIG); | ||
| 336 | |||
| 337 | /* Set CK_OUT_EN bit to 1. */ | ||
| 338 | writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) | ||
| 339 | | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG); | ||
| 340 | |||
| 341 | /* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */ | ||
| 342 | while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) & | ||
| 343 | CORE_DLL_LOCK)) { | ||
| 344 | /* max. wait for 50us sec for LOCK bit to be set */ | ||
| 345 | if (--wait_cnt == 0) { | ||
| 346 | dev_err(mmc_dev(mmc), "%s: DLL failed to LOCK\n", | ||
| 347 | mmc_hostname(mmc)); | ||
| 348 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 349 | return -ETIMEDOUT; | ||
| 350 | } | ||
| 351 | udelay(1); | ||
| 352 | } | ||
| 353 | |||
| 354 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode) | ||
| 359 | { | ||
| 360 | int tuning_seq_cnt = 3; | ||
| 361 | u8 phase, *data_buf, tuned_phases[16], tuned_phase_cnt = 0; | ||
| 362 | const u32 *tuning_block_pattern = tuning_block_64; | ||
| 363 | int size = sizeof(tuning_block_64); /* Pattern size in bytes */ | ||
| 364 | int rc; | ||
| 365 | struct mmc_host *mmc = host->mmc; | ||
| 366 | struct mmc_ios ios = host->mmc->ios; | ||
| 367 | |||
| 368 | /* | ||
| 369 | * Tuning is required for SDR104, HS200 and HS400 cards and | ||
| 370 | * if clock frequency is greater than 100MHz in these modes. | ||
| 371 | */ | ||
| 372 | if (host->clock <= 100 * 1000 * 1000 || | ||
| 373 | !((ios.timing == MMC_TIMING_MMC_HS200) || | ||
| 374 | (ios.timing == MMC_TIMING_UHS_SDR104))) | ||
| 375 | return 0; | ||
| 376 | |||
| 377 | if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) && | ||
| 378 | (mmc->ios.bus_width == MMC_BUS_WIDTH_8)) { | ||
| 379 | tuning_block_pattern = tuning_block_128; | ||
| 380 | size = sizeof(tuning_block_128); | ||
| 381 | } | ||
| 382 | |||
| 383 | data_buf = kmalloc(size, GFP_KERNEL); | ||
| 384 | if (!data_buf) | ||
| 385 | return -ENOMEM; | ||
| 386 | |||
| 387 | retry: | ||
| 388 | /* First of all reset the tuning block */ | ||
| 389 | rc = msm_init_cm_dll(host); | ||
| 390 | if (rc) | ||
| 391 | goto out; | ||
| 392 | |||
| 393 | phase = 0; | ||
| 394 | do { | ||
| 395 | struct mmc_command cmd = { 0 }; | ||
| 396 | struct mmc_data data = { 0 }; | ||
| 397 | struct mmc_request mrq = { | ||
| 398 | .cmd = &cmd, | ||
| 399 | .data = &data | ||
| 400 | }; | ||
| 401 | struct scatterlist sg; | ||
| 402 | |||
| 403 | /* Set the phase in delay line hw block */ | ||
| 404 | rc = msm_config_cm_dll_phase(host, phase); | ||
| 405 | if (rc) | ||
| 406 | goto out; | ||
| 407 | |||
| 408 | cmd.opcode = opcode; | ||
| 409 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | ||
| 410 | |||
| 411 | data.blksz = size; | ||
| 412 | data.blocks = 1; | ||
| 413 | data.flags = MMC_DATA_READ; | ||
| 414 | data.timeout_ns = NSEC_PER_SEC; /* 1 second */ | ||
| 415 | |||
| 416 | data.sg = &sg; | ||
| 417 | data.sg_len = 1; | ||
| 418 | sg_init_one(&sg, data_buf, size); | ||
| 419 | memset(data_buf, 0, size); | ||
| 420 | mmc_wait_for_req(mmc, &mrq); | ||
| 421 | |||
| 422 | if (!cmd.error && !data.error && | ||
| 423 | !memcmp(data_buf, tuning_block_pattern, size)) { | ||
| 424 | /* Tuning is successful at this tuning point */ | ||
| 425 | tuned_phases[tuned_phase_cnt++] = phase; | ||
| 426 | dev_dbg(mmc_dev(mmc), "%s: Found good phase = %d\n", | ||
| 427 | mmc_hostname(mmc), phase); | ||
| 428 | } | ||
| 429 | } while (++phase < ARRAY_SIZE(tuned_phases)); | ||
| 430 | |||
| 431 | if (tuned_phase_cnt) { | ||
| 432 | rc = msm_find_most_appropriate_phase(host, tuned_phases, | ||
| 433 | tuned_phase_cnt); | ||
| 434 | if (rc < 0) | ||
| 435 | goto out; | ||
| 436 | else | ||
| 437 | phase = rc; | ||
| 438 | |||
| 439 | /* | ||
| 440 | * Finally set the selected phase in delay | ||
| 441 | * line hw block. | ||
| 442 | */ | ||
| 443 | rc = msm_config_cm_dll_phase(host, phase); | ||
| 444 | if (rc) | ||
| 445 | goto out; | ||
| 446 | dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n", | ||
| 447 | mmc_hostname(mmc), phase); | ||
| 448 | } else { | ||
| 449 | if (--tuning_seq_cnt) | ||
| 450 | goto retry; | ||
| 451 | /* Tuning failed */ | ||
| 452 | dev_dbg(mmc_dev(mmc), "%s: No tuning point found\n", | ||
| 453 | mmc_hostname(mmc)); | ||
| 454 | rc = -EIO; | ||
| 455 | } | ||
| 456 | |||
| 457 | out: | ||
| 458 | kfree(data_buf); | ||
| 459 | return rc; | ||
| 460 | } | ||
| 461 | |||
| 462 | static const struct of_device_id sdhci_msm_dt_match[] = { | ||
| 463 | { .compatible = "qcom,sdhci-msm-v4" }, | ||
| 464 | {}, | ||
| 465 | }; | ||
| 466 | |||
| 467 | MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match); | ||
| 468 | |||
| 469 | static struct sdhci_ops sdhci_msm_ops = { | ||
| 470 | .platform_execute_tuning = sdhci_msm_execute_tuning, | ||
| 471 | }; | ||
| 472 | |||
| 473 | static int sdhci_msm_probe(struct platform_device *pdev) | ||
| 474 | { | ||
| 475 | struct sdhci_host *host; | ||
| 476 | struct sdhci_pltfm_host *pltfm_host; | ||
| 477 | struct sdhci_msm_host *msm_host; | ||
| 478 | struct resource *core_memres; | ||
| 479 | int ret; | ||
| 480 | u16 host_version; | ||
| 481 | |||
| 482 | msm_host = devm_kzalloc(&pdev->dev, sizeof(*msm_host), GFP_KERNEL); | ||
| 483 | if (!msm_host) | ||
| 484 | return -ENOMEM; | ||
| 485 | |||
| 486 | msm_host->sdhci_msm_pdata.ops = &sdhci_msm_ops; | ||
| 487 | host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0); | ||
| 488 | if (IS_ERR(host)) | ||
| 489 | return PTR_ERR(host); | ||
| 490 | |||
| 491 | pltfm_host = sdhci_priv(host); | ||
| 492 | pltfm_host->priv = msm_host; | ||
| 493 | msm_host->mmc = host->mmc; | ||
| 494 | msm_host->pdev = pdev; | ||
| 495 | |||
| 496 | ret = mmc_of_parse(host->mmc); | ||
| 497 | if (ret) | ||
| 498 | goto pltfm_free; | ||
| 499 | |||
| 500 | sdhci_get_of_property(pdev); | ||
| 501 | |||
| 502 | /* Setup SDCC bus voter clock. */ | ||
| 503 | msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); | ||
| 504 | if (!IS_ERR(msm_host->bus_clk)) { | ||
| 505 | /* Vote for max. clk rate for max. performance */ | ||
| 506 | ret = clk_set_rate(msm_host->bus_clk, INT_MAX); | ||
| 507 | if (ret) | ||
| 508 | goto pltfm_free; | ||
| 509 | ret = clk_prepare_enable(msm_host->bus_clk); | ||
| 510 | if (ret) | ||
| 511 | goto pltfm_free; | ||
| 512 | } | ||
| 513 | |||
| 514 | /* Setup main peripheral bus clock */ | ||
| 515 | msm_host->pclk = devm_clk_get(&pdev->dev, "iface"); | ||
| 516 | if (IS_ERR(msm_host->pclk)) { | ||
| 517 | ret = PTR_ERR(msm_host->pclk); | ||
| 518 | dev_err(&pdev->dev, "Perpheral clk setup failed (%d)\n", ret); | ||
| 519 | goto bus_clk_disable; | ||
| 520 | } | ||
| 521 | |||
| 522 | ret = clk_prepare_enable(msm_host->pclk); | ||
| 523 | if (ret) | ||
| 524 | goto bus_clk_disable; | ||
| 525 | |||
| 526 | /* Setup SDC MMC clock */ | ||
| 527 | msm_host->clk = devm_clk_get(&pdev->dev, "core"); | ||
| 528 | if (IS_ERR(msm_host->clk)) { | ||
| 529 | ret = PTR_ERR(msm_host->clk); | ||
| 530 | dev_err(&pdev->dev, "SDC MMC clk setup failed (%d)\n", ret); | ||
| 531 | goto pclk_disable; | ||
| 532 | } | ||
| 533 | |||
| 534 | ret = clk_prepare_enable(msm_host->clk); | ||
| 535 | if (ret) | ||
| 536 | goto pclk_disable; | ||
| 537 | |||
| 538 | core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 539 | msm_host->core_mem = devm_ioremap_resource(&pdev->dev, core_memres); | ||
| 540 | |||
| 541 | if (IS_ERR(msm_host->core_mem)) { | ||
| 542 | dev_err(&pdev->dev, "Failed to remap registers\n"); | ||
| 543 | ret = PTR_ERR(msm_host->core_mem); | ||
| 544 | goto clk_disable; | ||
| 545 | } | ||
| 546 | |||
| 547 | /* Reset the core and Enable SDHC mode */ | ||
| 548 | writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) | | ||
| 549 | CORE_SW_RST, msm_host->core_mem + CORE_POWER); | ||
| 550 | |||
| 551 | /* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */ | ||
| 552 | usleep_range(1000, 5000); | ||
| 553 | if (readl(msm_host->core_mem + CORE_POWER) & CORE_SW_RST) { | ||
| 554 | dev_err(&pdev->dev, "Stuck in reset\n"); | ||
| 555 | ret = -ETIMEDOUT; | ||
| 556 | goto clk_disable; | ||
| 557 | } | ||
| 558 | |||
| 559 | /* Set HC_MODE_EN bit in HC_MODE register */ | ||
| 560 | writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE)); | ||
| 561 | |||
| 562 | host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; | ||
| 563 | host->quirks |= SDHCI_QUIRK_SINGLE_POWER_WRITE; | ||
| 564 | |||
| 565 | host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); | ||
| 566 | dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n", | ||
| 567 | host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >> | ||
| 568 | SDHCI_VENDOR_VER_SHIFT)); | ||
| 569 | |||
| 570 | ret = sdhci_add_host(host); | ||
| 571 | if (ret) | ||
| 572 | goto clk_disable; | ||
| 573 | |||
| 574 | return 0; | ||
| 575 | |||
| 576 | clk_disable: | ||
| 577 | clk_disable_unprepare(msm_host->clk); | ||
| 578 | pclk_disable: | ||
| 579 | clk_disable_unprepare(msm_host->pclk); | ||
| 580 | bus_clk_disable: | ||
| 581 | if (!IS_ERR(msm_host->bus_clk)) | ||
| 582 | clk_disable_unprepare(msm_host->bus_clk); | ||
| 583 | pltfm_free: | ||
| 584 | sdhci_pltfm_free(pdev); | ||
| 585 | return ret; | ||
| 586 | } | ||
| 587 | |||
| 588 | static int sdhci_msm_remove(struct platform_device *pdev) | ||
| 589 | { | ||
| 590 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
| 591 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 592 | struct sdhci_msm_host *msm_host = pltfm_host->priv; | ||
| 593 | int dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) == | ||
| 594 | 0xffffffff); | ||
| 595 | |||
| 596 | sdhci_remove_host(host, dead); | ||
| 597 | sdhci_pltfm_free(pdev); | ||
| 598 | clk_disable_unprepare(msm_host->clk); | ||
| 599 | clk_disable_unprepare(msm_host->pclk); | ||
| 600 | if (!IS_ERR(msm_host->bus_clk)) | ||
| 601 | clk_disable_unprepare(msm_host->bus_clk); | ||
| 602 | return 0; | ||
| 603 | } | ||
| 604 | |||
| 605 | static struct platform_driver sdhci_msm_driver = { | ||
| 606 | .probe = sdhci_msm_probe, | ||
| 607 | .remove = sdhci_msm_remove, | ||
| 608 | .driver = { | ||
| 609 | .name = "sdhci_msm", | ||
| 610 | .owner = THIS_MODULE, | ||
| 611 | .of_match_table = sdhci_msm_dt_match, | ||
| 612 | }, | ||
| 613 | }; | ||
| 614 | |||
| 615 | module_platform_driver(sdhci_msm_driver); | ||
| 616 | |||
| 617 | MODULE_DESCRIPTION("Qualcomm Secure Digital Host Controller Interface driver"); | ||
| 618 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 0955777b6c7e..fdc612120362 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -610,6 +610,18 @@ static const struct sdhci_pci_fixes sdhci_via = { | |||
| 610 | .probe = via_probe, | 610 | .probe = via_probe, |
| 611 | }; | 611 | }; |
| 612 | 612 | ||
| 613 | static int rtsx_probe_slot(struct sdhci_pci_slot *slot) | ||
| 614 | { | ||
| 615 | slot->host->mmc->caps2 |= MMC_CAP2_HS200; | ||
| 616 | return 0; | ||
| 617 | } | ||
| 618 | |||
| 619 | static const struct sdhci_pci_fixes sdhci_rtsx = { | ||
| 620 | .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | | ||
| 621 | SDHCI_QUIRK2_BROKEN_DDR50, | ||
| 622 | .probe_slot = rtsx_probe_slot, | ||
| 623 | }; | ||
| 624 | |||
| 613 | static const struct pci_device_id pci_ids[] = { | 625 | static const struct pci_device_id pci_ids[] = { |
| 614 | { | 626 | { |
| 615 | .vendor = PCI_VENDOR_ID_RICOH, | 627 | .vendor = PCI_VENDOR_ID_RICOH, |
| @@ -732,6 +744,14 @@ static const struct pci_device_id pci_ids[] = { | |||
| 732 | }, | 744 | }, |
| 733 | 745 | ||
| 734 | { | 746 | { |
| 747 | .vendor = PCI_VENDOR_ID_REALTEK, | ||
| 748 | .device = 0x5250, | ||
| 749 | .subvendor = PCI_ANY_ID, | ||
| 750 | .subdevice = PCI_ANY_ID, | ||
| 751 | .driver_data = (kernel_ulong_t)&sdhci_rtsx, | ||
| 752 | }, | ||
| 753 | |||
| 754 | { | ||
| 735 | .vendor = PCI_VENDOR_ID_INTEL, | 755 | .vendor = PCI_VENDOR_ID_INTEL, |
| 736 | .device = PCI_DEVICE_ID_INTEL_MRST_SD0, | 756 | .device = PCI_DEVICE_ID_INTEL_MRST_SD0, |
| 737 | .subvendor = PCI_ANY_ID, | 757 | .subvendor = PCI_ANY_ID, |
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 793dacd3b841..2fd73b38c303 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/of_gpio.h> | 34 | #include <linux/of_gpio.h> |
| 35 | #include <linux/pm.h> | 35 | #include <linux/pm.h> |
| 36 | #include <linux/pm_runtime.h> | 36 | #include <linux/pm_runtime.h> |
| 37 | #include <linux/mbus.h> | ||
| 37 | 38 | ||
| 38 | #include "sdhci.h" | 39 | #include "sdhci.h" |
| 39 | #include "sdhci-pltfm.h" | 40 | #include "sdhci-pltfm.h" |
| @@ -57,6 +58,60 @@ | |||
| 57 | #define SDCE_MISC_INT (1<<2) | 58 | #define SDCE_MISC_INT (1<<2) |
| 58 | #define SDCE_MISC_INT_EN (1<<1) | 59 | #define SDCE_MISC_INT_EN (1<<1) |
| 59 | 60 | ||
| 61 | /* | ||
| 62 | * These registers are relative to the second register region, for the | ||
| 63 | * MBus bridge. | ||
| 64 | */ | ||
| 65 | #define SDHCI_WINDOW_CTRL(i) (0x80 + ((i) << 3)) | ||
| 66 | #define SDHCI_WINDOW_BASE(i) (0x84 + ((i) << 3)) | ||
| 67 | #define SDHCI_MAX_WIN_NUM 8 | ||
| 68 | |||
| 69 | static int mv_conf_mbus_windows(struct platform_device *pdev, | ||
| 70 | const struct mbus_dram_target_info *dram) | ||
| 71 | { | ||
| 72 | int i; | ||
| 73 | void __iomem *regs; | ||
| 74 | struct resource *res; | ||
| 75 | |||
| 76 | if (!dram) { | ||
| 77 | dev_err(&pdev->dev, "no mbus dram info\n"); | ||
| 78 | return -EINVAL; | ||
| 79 | } | ||
| 80 | |||
| 81 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 82 | if (!res) { | ||
| 83 | dev_err(&pdev->dev, "cannot get mbus registers\n"); | ||
| 84 | return -EINVAL; | ||
| 85 | } | ||
| 86 | |||
| 87 | regs = ioremap(res->start, resource_size(res)); | ||
| 88 | if (!regs) { | ||
| 89 | dev_err(&pdev->dev, "cannot map mbus registers\n"); | ||
| 90 | return -ENOMEM; | ||
| 91 | } | ||
| 92 | |||
| 93 | for (i = 0; i < SDHCI_MAX_WIN_NUM; i++) { | ||
| 94 | writel(0, regs + SDHCI_WINDOW_CTRL(i)); | ||
| 95 | writel(0, regs + SDHCI_WINDOW_BASE(i)); | ||
| 96 | } | ||
| 97 | |||
| 98 | for (i = 0; i < dram->num_cs; i++) { | ||
| 99 | const struct mbus_dram_window *cs = dram->cs + i; | ||
| 100 | |||
| 101 | /* Write size, attributes and target id to control register */ | ||
| 102 | writel(((cs->size - 1) & 0xffff0000) | | ||
| 103 | (cs->mbus_attr << 8) | | ||
| 104 | (dram->mbus_dram_target_id << 4) | 1, | ||
| 105 | regs + SDHCI_WINDOW_CTRL(i)); | ||
| 106 | /* Write base address to base register */ | ||
| 107 | writel(cs->base, regs + SDHCI_WINDOW_BASE(i)); | ||
| 108 | } | ||
| 109 | |||
| 110 | iounmap(regs); | ||
| 111 | |||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | |||
| 60 | static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask) | 115 | static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask) |
| 61 | { | 116 | { |
| 62 | struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); | 117 | struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); |
| @@ -187,6 +242,9 @@ static const struct of_device_id sdhci_pxav3_of_match[] = { | |||
| 187 | { | 242 | { |
| 188 | .compatible = "mrvl,pxav3-mmc", | 243 | .compatible = "mrvl,pxav3-mmc", |
| 189 | }, | 244 | }, |
| 245 | { | ||
| 246 | .compatible = "marvell,armada-380-sdhci", | ||
| 247 | }, | ||
| 190 | {}, | 248 | {}, |
| 191 | }; | 249 | }; |
| 192 | MODULE_DEVICE_TABLE(of, sdhci_pxav3_of_match); | 250 | MODULE_DEVICE_TABLE(of, sdhci_pxav3_of_match); |
| @@ -219,6 +277,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 219 | struct sdhci_pltfm_host *pltfm_host; | 277 | struct sdhci_pltfm_host *pltfm_host; |
| 220 | struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; | 278 | struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; |
| 221 | struct device *dev = &pdev->dev; | 279 | struct device *dev = &pdev->dev; |
| 280 | struct device_node *np = pdev->dev.of_node; | ||
| 222 | struct sdhci_host *host = NULL; | 281 | struct sdhci_host *host = NULL; |
| 223 | struct sdhci_pxa *pxa = NULL; | 282 | struct sdhci_pxa *pxa = NULL; |
| 224 | const struct of_device_id *match; | 283 | const struct of_device_id *match; |
| @@ -235,6 +294,14 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 235 | kfree(pxa); | 294 | kfree(pxa); |
| 236 | return PTR_ERR(host); | 295 | return PTR_ERR(host); |
| 237 | } | 296 | } |
| 297 | |||
| 298 | if (of_device_is_compatible(np, "marvell,armada-380-sdhci")) { | ||
| 299 | ret = mv_conf_mbus_windows(pdev, mv_mbus_dram_info()); | ||
| 300 | if (ret < 0) | ||
| 301 | goto err_mbus_win; | ||
| 302 | } | ||
| 303 | |||
| 304 | |||
| 238 | pltfm_host = sdhci_priv(host); | 305 | pltfm_host = sdhci_priv(host); |
| 239 | pltfm_host->priv = pxa; | 306 | pltfm_host->priv = pxa; |
| 240 | 307 | ||
| @@ -321,6 +388,7 @@ err_add_host: | |||
| 321 | clk_disable_unprepare(clk); | 388 | clk_disable_unprepare(clk); |
| 322 | clk_put(clk); | 389 | clk_put(clk); |
| 323 | err_clk_get: | 390 | err_clk_get: |
| 391 | err_mbus_win: | ||
| 324 | sdhci_pltfm_free(pdev); | 392 | sdhci_pltfm_free(pdev); |
| 325 | kfree(pxa); | 393 | kfree(pxa); |
| 326 | return ret; | 394 | return ret; |
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 6debda952155..d61eb5a70833 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
| @@ -51,12 +51,13 @@ struct sdhci_s3c { | |||
| 51 | struct platform_device *pdev; | 51 | struct platform_device *pdev; |
| 52 | struct resource *ioarea; | 52 | struct resource *ioarea; |
| 53 | struct s3c_sdhci_platdata *pdata; | 53 | struct s3c_sdhci_platdata *pdata; |
| 54 | unsigned int cur_clk; | 54 | int cur_clk; |
| 55 | int ext_cd_irq; | 55 | int ext_cd_irq; |
| 56 | int ext_cd_gpio; | 56 | int ext_cd_gpio; |
| 57 | 57 | ||
| 58 | struct clk *clk_io; | 58 | struct clk *clk_io; |
| 59 | struct clk *clk_bus[MAX_BUS_CLK]; | 59 | struct clk *clk_bus[MAX_BUS_CLK]; |
| 60 | unsigned long clk_rates[MAX_BUS_CLK]; | ||
| 60 | }; | 61 | }; |
| 61 | 62 | ||
| 62 | /** | 63 | /** |
| @@ -77,32 +78,6 @@ static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) | |||
| 77 | } | 78 | } |
| 78 | 79 | ||
| 79 | /** | 80 | /** |
| 80 | * get_curclk - convert ctrl2 register to clock source number | ||
| 81 | * @ctrl2: Control2 register value. | ||
| 82 | */ | ||
| 83 | static u32 get_curclk(u32 ctrl2) | ||
| 84 | { | ||
| 85 | ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK; | ||
| 86 | ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; | ||
| 87 | |||
| 88 | return ctrl2; | ||
| 89 | } | ||
| 90 | |||
| 91 | static void sdhci_s3c_check_sclk(struct sdhci_host *host) | ||
| 92 | { | ||
| 93 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
| 94 | u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2); | ||
| 95 | |||
| 96 | if (get_curclk(tmp) != ourhost->cur_clk) { | ||
| 97 | dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n"); | ||
| 98 | |||
| 99 | tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; | ||
| 100 | tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; | ||
| 101 | writel(tmp, host->ioaddr + S3C_SDHCI_CONTROL2); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 106 | * sdhci_s3c_get_max_clk - callback to get maximum clock frequency. | 81 | * sdhci_s3c_get_max_clk - callback to get maximum clock frequency. |
| 107 | * @host: The SDHCI host instance. | 82 | * @host: The SDHCI host instance. |
| 108 | * | 83 | * |
| @@ -111,20 +86,11 @@ static void sdhci_s3c_check_sclk(struct sdhci_host *host) | |||
| 111 | static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) | 86 | static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) |
| 112 | { | 87 | { |
| 113 | struct sdhci_s3c *ourhost = to_s3c(host); | 88 | struct sdhci_s3c *ourhost = to_s3c(host); |
| 114 | struct clk *busclk; | 89 | unsigned long rate, max = 0; |
| 115 | unsigned int rate, max; | 90 | int src; |
| 116 | int clk; | ||
| 117 | |||
| 118 | /* note, a reset will reset the clock source */ | ||
| 119 | |||
| 120 | sdhci_s3c_check_sclk(host); | ||
| 121 | |||
| 122 | for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) { | ||
| 123 | busclk = ourhost->clk_bus[clk]; | ||
| 124 | if (!busclk) | ||
| 125 | continue; | ||
| 126 | 91 | ||
| 127 | rate = clk_get_rate(busclk); | 92 | for (src = 0; src < MAX_BUS_CLK; src++) { |
| 93 | rate = ourhost->clk_rates[src]; | ||
| 128 | if (rate > max) | 94 | if (rate > max) |
| 129 | max = rate; | 95 | max = rate; |
| 130 | } | 96 | } |
| @@ -144,9 +110,9 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, | |||
| 144 | { | 110 | { |
| 145 | unsigned long rate; | 111 | unsigned long rate; |
| 146 | struct clk *clksrc = ourhost->clk_bus[src]; | 112 | struct clk *clksrc = ourhost->clk_bus[src]; |
| 147 | int div; | 113 | int shift; |
| 148 | 114 | ||
| 149 | if (!clksrc) | 115 | if (IS_ERR(clksrc)) |
| 150 | return UINT_MAX; | 116 | return UINT_MAX; |
| 151 | 117 | ||
| 152 | /* | 118 | /* |
| @@ -158,17 +124,24 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, | |||
| 158 | return wanted - rate; | 124 | return wanted - rate; |
| 159 | } | 125 | } |
| 160 | 126 | ||
| 161 | rate = clk_get_rate(clksrc); | 127 | rate = ourhost->clk_rates[src]; |
| 162 | 128 | ||
| 163 | for (div = 1; div < 256; div *= 2) { | 129 | for (shift = 0; shift <= 8; ++shift) { |
| 164 | if ((rate / div) <= wanted) | 130 | if ((rate >> shift) <= wanted) |
| 165 | break; | 131 | break; |
| 166 | } | 132 | } |
| 167 | 133 | ||
| 134 | if (shift > 8) { | ||
| 135 | dev_dbg(&ourhost->pdev->dev, | ||
| 136 | "clk %d: rate %ld, min rate %lu > wanted %u\n", | ||
| 137 | src, rate, rate / 256, wanted); | ||
| 138 | return UINT_MAX; | ||
| 139 | } | ||
| 140 | |||
| 168 | dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n", | 141 | dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n", |
| 169 | src, rate, wanted, rate / div); | 142 | src, rate, wanted, rate >> shift); |
| 170 | 143 | ||
| 171 | return wanted - (rate / div); | 144 | return wanted - (rate >> shift); |
| 172 | } | 145 | } |
| 173 | 146 | ||
| 174 | /** | 147 | /** |
| @@ -209,20 +182,22 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 209 | struct clk *clk = ourhost->clk_bus[best_src]; | 182 | struct clk *clk = ourhost->clk_bus[best_src]; |
| 210 | 183 | ||
| 211 | clk_prepare_enable(clk); | 184 | clk_prepare_enable(clk); |
| 212 | clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]); | 185 | if (ourhost->cur_clk >= 0) |
| 213 | 186 | clk_disable_unprepare( | |
| 214 | /* turn clock off to card before changing clock source */ | 187 | ourhost->clk_bus[ourhost->cur_clk]); |
| 215 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); | ||
| 216 | 188 | ||
| 217 | ourhost->cur_clk = best_src; | 189 | ourhost->cur_clk = best_src; |
| 218 | host->max_clk = clk_get_rate(clk); | 190 | host->max_clk = ourhost->clk_rates[best_src]; |
| 219 | |||
| 220 | ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2); | ||
| 221 | ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; | ||
| 222 | ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; | ||
| 223 | writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2); | ||
| 224 | } | 191 | } |
| 225 | 192 | ||
| 193 | /* turn clock off to card before changing clock source */ | ||
| 194 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); | ||
| 195 | |||
| 196 | ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2); | ||
| 197 | ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; | ||
| 198 | ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; | ||
| 199 | writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2); | ||
| 200 | |||
| 226 | /* reprogram default hardware configuration */ | 201 | /* reprogram default hardware configuration */ |
| 227 | writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, | 202 | writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, |
| 228 | host->ioaddr + S3C64XX_SDHCI_CONTROL4); | 203 | host->ioaddr + S3C64XX_SDHCI_CONTROL4); |
| @@ -254,17 +229,17 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 254 | static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host) | 229 | static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host) |
| 255 | { | 230 | { |
| 256 | struct sdhci_s3c *ourhost = to_s3c(host); | 231 | struct sdhci_s3c *ourhost = to_s3c(host); |
| 257 | unsigned int delta, min = UINT_MAX; | 232 | unsigned long rate, min = ULONG_MAX; |
| 258 | int src; | 233 | int src; |
| 259 | 234 | ||
| 260 | for (src = 0; src < MAX_BUS_CLK; src++) { | 235 | for (src = 0; src < MAX_BUS_CLK; src++) { |
| 261 | delta = sdhci_s3c_consider_clock(ourhost, src, 0); | 236 | rate = ourhost->clk_rates[src] / 256; |
| 262 | if (delta == UINT_MAX) | 237 | if (!rate) |
| 263 | continue; | 238 | continue; |
| 264 | /* delta is a negative value in this case */ | 239 | if (rate < min) |
| 265 | if (-delta < min) | 240 | min = rate; |
| 266 | min = -delta; | ||
| 267 | } | 241 | } |
| 242 | |||
| 268 | return min; | 243 | return min; |
| 269 | } | 244 | } |
| 270 | 245 | ||
| @@ -272,20 +247,44 @@ static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host) | |||
| 272 | static unsigned int sdhci_cmu_get_max_clock(struct sdhci_host *host) | 247 | static unsigned int sdhci_cmu_get_max_clock(struct sdhci_host *host) |
| 273 | { | 248 | { |
| 274 | struct sdhci_s3c *ourhost = to_s3c(host); | 249 | struct sdhci_s3c *ourhost = to_s3c(host); |
| 250 | unsigned long rate, max = 0; | ||
| 251 | int src; | ||
| 275 | 252 | ||
| 276 | return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], UINT_MAX); | 253 | for (src = 0; src < MAX_BUS_CLK; src++) { |
| 254 | struct clk *clk; | ||
| 255 | |||
| 256 | clk = ourhost->clk_bus[src]; | ||
| 257 | if (IS_ERR(clk)) | ||
| 258 | continue; | ||
| 259 | |||
| 260 | rate = clk_round_rate(clk, ULONG_MAX); | ||
| 261 | if (rate > max) | ||
| 262 | max = rate; | ||
| 263 | } | ||
| 264 | |||
| 265 | return max; | ||
| 277 | } | 266 | } |
| 278 | 267 | ||
| 279 | /* sdhci_cmu_get_min_clock - callback to get minimal supported clock value. */ | 268 | /* sdhci_cmu_get_min_clock - callback to get minimal supported clock value. */ |
| 280 | static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host) | 269 | static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host) |
| 281 | { | 270 | { |
| 282 | struct sdhci_s3c *ourhost = to_s3c(host); | 271 | struct sdhci_s3c *ourhost = to_s3c(host); |
| 272 | unsigned long rate, min = ULONG_MAX; | ||
| 273 | int src; | ||
| 283 | 274 | ||
| 284 | /* | 275 | for (src = 0; src < MAX_BUS_CLK; src++) { |
| 285 | * initial clock can be in the frequency range of | 276 | struct clk *clk; |
| 286 | * 100KHz-400KHz, so we set it as max value. | 277 | |
| 287 | */ | 278 | clk = ourhost->clk_bus[src]; |
| 288 | return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], 400000); | 279 | if (IS_ERR(clk)) |
| 280 | continue; | ||
| 281 | |||
| 282 | rate = clk_round_rate(clk, 0); | ||
| 283 | if (rate < min) | ||
| 284 | min = rate; | ||
| 285 | } | ||
| 286 | |||
| 287 | return min; | ||
| 289 | } | 288 | } |
| 290 | 289 | ||
| 291 | /* sdhci_cmu_set_clock - callback on clock change.*/ | 290 | /* sdhci_cmu_set_clock - callback on clock change.*/ |
| @@ -552,6 +551,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev) | |||
| 552 | sc->host = host; | 551 | sc->host = host; |
| 553 | sc->pdev = pdev; | 552 | sc->pdev = pdev; |
| 554 | sc->pdata = pdata; | 553 | sc->pdata = pdata; |
| 554 | sc->cur_clk = -1; | ||
| 555 | 555 | ||
| 556 | platform_set_drvdata(pdev, host); | 556 | platform_set_drvdata(pdev, host); |
| 557 | 557 | ||
| @@ -566,25 +566,18 @@ static int sdhci_s3c_probe(struct platform_device *pdev) | |||
| 566 | clk_prepare_enable(sc->clk_io); | 566 | clk_prepare_enable(sc->clk_io); |
| 567 | 567 | ||
| 568 | for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { | 568 | for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { |
| 569 | struct clk *clk; | ||
| 570 | char name[14]; | 569 | char name[14]; |
| 571 | 570 | ||
| 572 | snprintf(name, 14, "mmc_busclk.%d", ptr); | 571 | snprintf(name, 14, "mmc_busclk.%d", ptr); |
| 573 | clk = devm_clk_get(dev, name); | 572 | sc->clk_bus[ptr] = devm_clk_get(dev, name); |
| 574 | if (IS_ERR(clk)) | 573 | if (IS_ERR(sc->clk_bus[ptr])) |
| 575 | continue; | 574 | continue; |
| 576 | 575 | ||
| 577 | clks++; | 576 | clks++; |
| 578 | sc->clk_bus[ptr] = clk; | 577 | sc->clk_rates[ptr] = clk_get_rate(sc->clk_bus[ptr]); |
| 579 | |||
| 580 | /* | ||
| 581 | * save current clock index to know which clock bus | ||
| 582 | * is used later in overriding functions. | ||
| 583 | */ | ||
| 584 | sc->cur_clk = ptr; | ||
| 585 | 578 | ||
| 586 | dev_info(dev, "clock source %d: %s (%ld Hz)\n", | 579 | dev_info(dev, "clock source %d: %s (%ld Hz)\n", |
| 587 | ptr, name, clk_get_rate(clk)); | 580 | ptr, name, sc->clk_rates[ptr]); |
| 588 | } | 581 | } |
| 589 | 582 | ||
| 590 | if (clks == 0) { | 583 | if (clks == 0) { |
| @@ -593,10 +586,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev) | |||
| 593 | goto err_no_busclks; | 586 | goto err_no_busclks; |
| 594 | } | 587 | } |
| 595 | 588 | ||
| 596 | #ifndef CONFIG_PM_RUNTIME | ||
| 597 | clk_prepare_enable(sc->clk_bus[sc->cur_clk]); | ||
| 598 | #endif | ||
| 599 | |||
| 600 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 589 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 601 | host->ioaddr = devm_ioremap_resource(&pdev->dev, res); | 590 | host->ioaddr = devm_ioremap_resource(&pdev->dev, res); |
| 602 | if (IS_ERR(host->ioaddr)) { | 591 | if (IS_ERR(host->ioaddr)) { |
| @@ -709,10 +698,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev) | |||
| 709 | return 0; | 698 | return 0; |
| 710 | 699 | ||
| 711 | err_req_regs: | 700 | err_req_regs: |
| 712 | #ifndef CONFIG_PM_RUNTIME | ||
| 713 | clk_disable_unprepare(sc->clk_bus[sc->cur_clk]); | ||
| 714 | #endif | ||
| 715 | |||
| 716 | err_no_busclks: | 701 | err_no_busclks: |
| 717 | clk_disable_unprepare(sc->clk_io); | 702 | clk_disable_unprepare(sc->clk_io); |
| 718 | 703 | ||
| @@ -743,9 +728,6 @@ static int sdhci_s3c_remove(struct platform_device *pdev) | |||
| 743 | pm_runtime_dont_use_autosuspend(&pdev->dev); | 728 | pm_runtime_dont_use_autosuspend(&pdev->dev); |
| 744 | pm_runtime_disable(&pdev->dev); | 729 | pm_runtime_disable(&pdev->dev); |
| 745 | 730 | ||
| 746 | #ifndef CONFIG_PM_RUNTIME | ||
| 747 | clk_disable_unprepare(sc->clk_bus[sc->cur_clk]); | ||
| 748 | #endif | ||
| 749 | clk_disable_unprepare(sc->clk_io); | 731 | clk_disable_unprepare(sc->clk_io); |
| 750 | 732 | ||
| 751 | sdhci_free_host(host); | 733 | sdhci_free_host(host); |
| @@ -779,7 +761,8 @@ static int sdhci_s3c_runtime_suspend(struct device *dev) | |||
| 779 | 761 | ||
| 780 | ret = sdhci_runtime_suspend_host(host); | 762 | ret = sdhci_runtime_suspend_host(host); |
| 781 | 763 | ||
| 782 | clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]); | 764 | if (ourhost->cur_clk >= 0) |
| 765 | clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]); | ||
| 783 | clk_disable_unprepare(busclk); | 766 | clk_disable_unprepare(busclk); |
| 784 | return ret; | 767 | return ret; |
| 785 | } | 768 | } |
| @@ -792,7 +775,8 @@ static int sdhci_s3c_runtime_resume(struct device *dev) | |||
| 792 | int ret; | 775 | int ret; |
| 793 | 776 | ||
| 794 | clk_prepare_enable(busclk); | 777 | clk_prepare_enable(busclk); |
| 795 | clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]); | 778 | if (ourhost->cur_clk >= 0) |
| 779 | clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]); | ||
| 796 | ret = sdhci_runtime_resume_host(host); | 780 | ret = sdhci_runtime_resume_host(host); |
| 797 | return ret; | 781 | return ret; |
| 798 | } | 782 | } |
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index 2dba9f8d1760..0316dec3f006 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/mmc/host.h> | 28 | #include <linux/mmc/host.h> |
| 29 | #include <linux/mmc/sdhci-spear.h> | 29 | #include <linux/mmc/sdhci-spear.h> |
| 30 | #include <linux/mmc/slot-gpio.h> | ||
| 30 | #include <linux/io.h> | 31 | #include <linux/io.h> |
| 31 | #include "sdhci.h" | 32 | #include "sdhci.h" |
| 32 | 33 | ||
| @@ -40,36 +41,6 @@ static const struct sdhci_ops sdhci_pltfm_ops = { | |||
| 40 | /* Nothing to do for now. */ | 41 | /* Nothing to do for now. */ |
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| 43 | /* gpio card detection interrupt handler */ | ||
| 44 | static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id) | ||
| 45 | { | ||
| 46 | struct platform_device *pdev = dev_id; | ||
| 47 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
| 48 | struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev); | ||
| 49 | unsigned long gpio_irq_type; | ||
| 50 | int val; | ||
| 51 | |||
| 52 | val = gpio_get_value(sdhci->data->card_int_gpio); | ||
| 53 | |||
| 54 | /* val == 1 -> card removed, val == 0 -> card inserted */ | ||
| 55 | /* if card removed - set irq for low level, else vice versa */ | ||
| 56 | gpio_irq_type = val ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH; | ||
| 57 | irq_set_irq_type(irq, gpio_irq_type); | ||
| 58 | |||
| 59 | if (sdhci->data->card_power_gpio >= 0) { | ||
| 60 | if (!sdhci->data->power_always_enb) { | ||
| 61 | /* if card inserted, give power, otherwise remove it */ | ||
| 62 | val = sdhci->data->power_active_high ? !val : val ; | ||
| 63 | gpio_set_value(sdhci->data->card_power_gpio, val); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | /* inform sdhci driver about card insertion/removal */ | ||
| 68 | tasklet_schedule(&host->card_tasklet); | ||
| 69 | |||
| 70 | return IRQ_HANDLED; | ||
| 71 | } | ||
| 72 | |||
| 73 | #ifdef CONFIG_OF | 44 | #ifdef CONFIG_OF |
| 74 | static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev) | 45 | static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev) |
| 75 | { | 46 | { |
| @@ -84,14 +55,12 @@ static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pde | |||
| 84 | /* If pdata is required */ | 55 | /* If pdata is required */ |
| 85 | if (cd_gpio != -1) { | 56 | if (cd_gpio != -1) { |
| 86 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 57 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
| 87 | if (!pdata) { | 58 | if (!pdata) |
| 88 | dev_err(&pdev->dev, "DT: kzalloc failed\n"); | 59 | dev_err(&pdev->dev, "DT: kzalloc failed\n"); |
| 89 | return ERR_PTR(-ENOMEM); | 60 | else |
| 90 | } | 61 | pdata->card_int_gpio = cd_gpio; |
| 91 | } | 62 | } |
| 92 | 63 | ||
| 93 | pdata->card_int_gpio = cd_gpio; | ||
| 94 | |||
| 95 | return pdata; | 64 | return pdata; |
| 96 | } | 65 | } |
| 97 | #else | 66 | #else |
| @@ -107,41 +76,44 @@ static int sdhci_probe(struct platform_device *pdev) | |||
| 107 | struct sdhci_host *host; | 76 | struct sdhci_host *host; |
| 108 | struct resource *iomem; | 77 | struct resource *iomem; |
| 109 | struct spear_sdhci *sdhci; | 78 | struct spear_sdhci *sdhci; |
| 79 | struct device *dev; | ||
| 110 | int ret; | 80 | int ret; |
| 111 | 81 | ||
| 112 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 82 | dev = pdev->dev.parent ? pdev->dev.parent : &pdev->dev; |
| 113 | if (!iomem) { | 83 | host = sdhci_alloc_host(dev, sizeof(*sdhci)); |
| 114 | ret = -ENOMEM; | 84 | if (IS_ERR(host)) { |
| 115 | dev_dbg(&pdev->dev, "memory resource not defined\n"); | 85 | ret = PTR_ERR(host); |
| 86 | dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n"); | ||
| 116 | goto err; | 87 | goto err; |
| 117 | } | 88 | } |
| 118 | 89 | ||
| 119 | if (!devm_request_mem_region(&pdev->dev, iomem->start, | 90 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 120 | resource_size(iomem), "spear-sdhci")) { | 91 | host->ioaddr = devm_ioremap_resource(&pdev->dev, iomem); |
| 121 | ret = -EBUSY; | 92 | if (IS_ERR(host->ioaddr)) { |
| 122 | dev_dbg(&pdev->dev, "cannot request region\n"); | 93 | ret = PTR_ERR(host->ioaddr); |
| 123 | goto err; | 94 | dev_dbg(&pdev->dev, "unable to map iomem: %d\n", ret); |
| 95 | goto err_host; | ||
| 124 | } | 96 | } |
| 125 | 97 | ||
| 126 | sdhci = devm_kzalloc(&pdev->dev, sizeof(*sdhci), GFP_KERNEL); | 98 | host->hw_name = "sdhci"; |
| 127 | if (!sdhci) { | 99 | host->ops = &sdhci_pltfm_ops; |
| 128 | ret = -ENOMEM; | 100 | host->irq = platform_get_irq(pdev, 0); |
| 129 | dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n"); | 101 | host->quirks = SDHCI_QUIRK_BROKEN_ADMA; |
| 130 | goto err; | 102 | |
| 131 | } | 103 | sdhci = sdhci_priv(host); |
| 132 | 104 | ||
| 133 | /* clk enable */ | 105 | /* clk enable */ |
| 134 | sdhci->clk = clk_get(&pdev->dev, NULL); | 106 | sdhci->clk = devm_clk_get(&pdev->dev, NULL); |
| 135 | if (IS_ERR(sdhci->clk)) { | 107 | if (IS_ERR(sdhci->clk)) { |
| 136 | ret = PTR_ERR(sdhci->clk); | 108 | ret = PTR_ERR(sdhci->clk); |
| 137 | dev_dbg(&pdev->dev, "Error getting clock\n"); | 109 | dev_dbg(&pdev->dev, "Error getting clock\n"); |
| 138 | goto err; | 110 | goto err_host; |
| 139 | } | 111 | } |
| 140 | 112 | ||
| 141 | ret = clk_prepare_enable(sdhci->clk); | 113 | ret = clk_prepare_enable(sdhci->clk); |
| 142 | if (ret) { | 114 | if (ret) { |
| 143 | dev_dbg(&pdev->dev, "Error enabling clock\n"); | 115 | dev_dbg(&pdev->dev, "Error enabling clock\n"); |
| 144 | goto put_clk; | 116 | goto err_host; |
| 145 | } | 117 | } |
| 146 | 118 | ||
| 147 | ret = clk_set_rate(sdhci->clk, 50000000); | 119 | ret = clk_set_rate(sdhci->clk, 50000000); |
| @@ -153,118 +125,42 @@ static int sdhci_probe(struct platform_device *pdev) | |||
| 153 | sdhci->data = sdhci_probe_config_dt(pdev); | 125 | sdhci->data = sdhci_probe_config_dt(pdev); |
| 154 | if (IS_ERR(sdhci->data)) { | 126 | if (IS_ERR(sdhci->data)) { |
| 155 | dev_err(&pdev->dev, "DT: Failed to get pdata\n"); | 127 | dev_err(&pdev->dev, "DT: Failed to get pdata\n"); |
| 156 | return -ENODEV; | 128 | goto disable_clk; |
| 157 | } | 129 | } |
| 158 | } else { | 130 | } else { |
| 159 | sdhci->data = dev_get_platdata(&pdev->dev); | 131 | sdhci->data = dev_get_platdata(&pdev->dev); |
| 160 | } | 132 | } |
| 161 | 133 | ||
| 162 | pdev->dev.platform_data = sdhci; | 134 | /* |
| 163 | 135 | * It is optional to use GPIOs for sdhci card detection. If | |
| 164 | if (pdev->dev.parent) | 136 | * sdhci->data is NULL, then use original sdhci lines otherwise |
| 165 | host = sdhci_alloc_host(pdev->dev.parent, 0); | 137 | * GPIO lines. We use the built-in GPIO support for this. |
| 166 | else | 138 | */ |
| 167 | host = sdhci_alloc_host(&pdev->dev, 0); | 139 | if (sdhci->data && sdhci->data->card_int_gpio >= 0) { |
| 168 | 140 | ret = mmc_gpio_request_cd(host->mmc, | |
| 169 | if (IS_ERR(host)) { | 141 | sdhci->data->card_int_gpio, 0); |
| 170 | ret = PTR_ERR(host); | 142 | if (ret < 0) { |
| 171 | dev_dbg(&pdev->dev, "error allocating host\n"); | 143 | dev_dbg(&pdev->dev, |
| 172 | goto disable_clk; | 144 | "failed to request card-detect gpio%d\n", |
| 173 | } | 145 | sdhci->data->card_int_gpio); |
| 174 | 146 | goto disable_clk; | |
| 175 | host->hw_name = "sdhci"; | 147 | } |
| 176 | host->ops = &sdhci_pltfm_ops; | ||
| 177 | host->irq = platform_get_irq(pdev, 0); | ||
| 178 | host->quirks = SDHCI_QUIRK_BROKEN_ADMA; | ||
| 179 | |||
| 180 | host->ioaddr = devm_ioremap(&pdev->dev, iomem->start, | ||
| 181 | resource_size(iomem)); | ||
| 182 | if (!host->ioaddr) { | ||
| 183 | ret = -ENOMEM; | ||
| 184 | dev_dbg(&pdev->dev, "failed to remap registers\n"); | ||
| 185 | goto free_host; | ||
| 186 | } | 148 | } |
| 187 | 149 | ||
| 188 | ret = sdhci_add_host(host); | 150 | ret = sdhci_add_host(host); |
| 189 | if (ret) { | 151 | if (ret) { |
| 190 | dev_dbg(&pdev->dev, "error adding host\n"); | 152 | dev_dbg(&pdev->dev, "error adding host\n"); |
| 191 | goto free_host; | 153 | goto disable_clk; |
| 192 | } | 154 | } |
| 193 | 155 | ||
| 194 | platform_set_drvdata(pdev, host); | 156 | platform_set_drvdata(pdev, host); |
| 195 | 157 | ||
| 196 | /* | ||
| 197 | * It is optional to use GPIOs for sdhci Power control & sdhci card | ||
| 198 | * interrupt detection. If sdhci->data is NULL, then use original sdhci | ||
| 199 | * lines otherwise GPIO lines. | ||
| 200 | * If GPIO is selected for power control, then power should be disabled | ||
| 201 | * after card removal and should be enabled when card insertion | ||
| 202 | * interrupt occurs | ||
| 203 | */ | ||
| 204 | if (!sdhci->data) | ||
| 205 | return 0; | ||
| 206 | |||
| 207 | if (sdhci->data->card_power_gpio >= 0) { | ||
| 208 | int val = 0; | ||
| 209 | |||
| 210 | ret = devm_gpio_request(&pdev->dev, | ||
| 211 | sdhci->data->card_power_gpio, "sdhci"); | ||
| 212 | if (ret < 0) { | ||
| 213 | dev_dbg(&pdev->dev, "gpio request fail: %d\n", | ||
| 214 | sdhci->data->card_power_gpio); | ||
| 215 | goto set_drvdata; | ||
| 216 | } | ||
| 217 | |||
| 218 | if (sdhci->data->power_always_enb) | ||
| 219 | val = sdhci->data->power_active_high; | ||
| 220 | else | ||
| 221 | val = !sdhci->data->power_active_high; | ||
| 222 | |||
| 223 | ret = gpio_direction_output(sdhci->data->card_power_gpio, val); | ||
| 224 | if (ret) { | ||
| 225 | dev_dbg(&pdev->dev, "gpio set direction fail: %d\n", | ||
| 226 | sdhci->data->card_power_gpio); | ||
| 227 | goto set_drvdata; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | if (sdhci->data->card_int_gpio >= 0) { | ||
| 232 | ret = devm_gpio_request(&pdev->dev, sdhci->data->card_int_gpio, | ||
| 233 | "sdhci"); | ||
| 234 | if (ret < 0) { | ||
| 235 | dev_dbg(&pdev->dev, "gpio request fail: %d\n", | ||
| 236 | sdhci->data->card_int_gpio); | ||
| 237 | goto set_drvdata; | ||
| 238 | } | ||
| 239 | |||
| 240 | ret = gpio_direction_input(sdhci->data->card_int_gpio); | ||
| 241 | if (ret) { | ||
| 242 | dev_dbg(&pdev->dev, "gpio set direction fail: %d\n", | ||
| 243 | sdhci->data->card_int_gpio); | ||
| 244 | goto set_drvdata; | ||
| 245 | } | ||
| 246 | ret = devm_request_irq(&pdev->dev, | ||
| 247 | gpio_to_irq(sdhci->data->card_int_gpio), | ||
| 248 | sdhci_gpio_irq, IRQF_TRIGGER_LOW, | ||
| 249 | mmc_hostname(host->mmc), pdev); | ||
| 250 | if (ret) { | ||
| 251 | dev_dbg(&pdev->dev, "gpio request irq fail: %d\n", | ||
| 252 | sdhci->data->card_int_gpio); | ||
| 253 | goto set_drvdata; | ||
| 254 | } | ||
| 255 | |||
| 256 | } | ||
| 257 | |||
| 258 | return 0; | 158 | return 0; |
| 259 | 159 | ||
| 260 | set_drvdata: | ||
| 261 | sdhci_remove_host(host, 1); | ||
| 262 | free_host: | ||
| 263 | sdhci_free_host(host); | ||
| 264 | disable_clk: | 160 | disable_clk: |
| 265 | clk_disable_unprepare(sdhci->clk); | 161 | clk_disable_unprepare(sdhci->clk); |
| 266 | put_clk: | 162 | err_host: |
| 267 | clk_put(sdhci->clk); | 163 | sdhci_free_host(host); |
| 268 | err: | 164 | err: |
| 269 | dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret); | 165 | dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret); |
| 270 | return ret; | 166 | return ret; |
| @@ -273,7 +169,7 @@ err: | |||
| 273 | static int sdhci_remove(struct platform_device *pdev) | 169 | static int sdhci_remove(struct platform_device *pdev) |
| 274 | { | 170 | { |
| 275 | struct sdhci_host *host = platform_get_drvdata(pdev); | 171 | struct sdhci_host *host = platform_get_drvdata(pdev); |
| 276 | struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev); | 172 | struct spear_sdhci *sdhci = sdhci_priv(host); |
| 277 | int dead = 0; | 173 | int dead = 0; |
| 278 | u32 scratch; | 174 | u32 scratch; |
| 279 | 175 | ||
| @@ -282,9 +178,8 @@ static int sdhci_remove(struct platform_device *pdev) | |||
| 282 | dead = 1; | 178 | dead = 1; |
| 283 | 179 | ||
| 284 | sdhci_remove_host(host, dead); | 180 | sdhci_remove_host(host, dead); |
| 285 | sdhci_free_host(host); | ||
| 286 | clk_disable_unprepare(sdhci->clk); | 181 | clk_disable_unprepare(sdhci->clk); |
| 287 | clk_put(sdhci->clk); | 182 | sdhci_free_host(host); |
| 288 | 183 | ||
| 289 | return 0; | 184 | return 0; |
| 290 | } | 185 | } |
| @@ -293,7 +188,7 @@ static int sdhci_remove(struct platform_device *pdev) | |||
| 293 | static int sdhci_suspend(struct device *dev) | 188 | static int sdhci_suspend(struct device *dev) |
| 294 | { | 189 | { |
| 295 | struct sdhci_host *host = dev_get_drvdata(dev); | 190 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 296 | struct spear_sdhci *sdhci = dev_get_platdata(dev); | 191 | struct spear_sdhci *sdhci = sdhci_priv(host); |
| 297 | int ret; | 192 | int ret; |
| 298 | 193 | ||
| 299 | ret = sdhci_suspend_host(host); | 194 | ret = sdhci_suspend_host(host); |
| @@ -306,7 +201,7 @@ static int sdhci_suspend(struct device *dev) | |||
| 306 | static int sdhci_resume(struct device *dev) | 201 | static int sdhci_resume(struct device *dev) |
| 307 | { | 202 | { |
| 308 | struct sdhci_host *host = dev_get_drvdata(dev); | 203 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 309 | struct spear_sdhci *sdhci = dev_get_platdata(dev); | 204 | struct spear_sdhci *sdhci = sdhci_priv(host); |
| 310 | int ret; | 205 | int ret; |
| 311 | 206 | ||
| 312 | ret = clk_enable(sdhci->clk); | 207 | ret = clk_enable(sdhci->clk); |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9ddef4763541..9a79fc4b60ca 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -675,12 +675,12 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) | |||
| 675 | return 0xE; | 675 | return 0xE; |
| 676 | 676 | ||
| 677 | /* Unspecified timeout, assume max */ | 677 | /* Unspecified timeout, assume max */ |
| 678 | if (!data && !cmd->cmd_timeout_ms) | 678 | if (!data && !cmd->busy_timeout) |
| 679 | return 0xE; | 679 | return 0xE; |
| 680 | 680 | ||
| 681 | /* timeout in us */ | 681 | /* timeout in us */ |
| 682 | if (!data) | 682 | if (!data) |
| 683 | target_timeout = cmd->cmd_timeout_ms * 1000; | 683 | target_timeout = cmd->busy_timeout * 1000; |
| 684 | else { | 684 | else { |
| 685 | target_timeout = data->timeout_ns / 1000; | 685 | target_timeout = data->timeout_ns / 1000; |
| 686 | if (host->clock) | 686 | if (host->clock) |
| @@ -1019,8 +1019,8 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
| 1019 | } | 1019 | } |
| 1020 | 1020 | ||
| 1021 | timeout = jiffies; | 1021 | timeout = jiffies; |
| 1022 | if (!cmd->data && cmd->cmd_timeout_ms > 9000) | 1022 | if (!cmd->data && cmd->busy_timeout > 9000) |
| 1023 | timeout += DIV_ROUND_UP(cmd->cmd_timeout_ms, 1000) * HZ + HZ; | 1023 | timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; |
| 1024 | else | 1024 | else |
| 1025 | timeout += 10 * HZ; | 1025 | timeout += 10 * HZ; |
| 1026 | mod_timer(&host->timer, timeout); | 1026 | mod_timer(&host->timer, timeout); |
| @@ -2026,12 +2026,11 @@ out: | |||
| 2026 | host->tuning_count * HZ); | 2026 | host->tuning_count * HZ); |
| 2027 | /* Tuning mode 1 limits the maximum data length to 4MB */ | 2027 | /* Tuning mode 1 limits the maximum data length to 4MB */ |
| 2028 | mmc->max_blk_count = (4 * 1024 * 1024) / mmc->max_blk_size; | 2028 | mmc->max_blk_count = (4 * 1024 * 1024) / mmc->max_blk_size; |
| 2029 | } else { | 2029 | } else if (host->flags & SDHCI_USING_RETUNING_TIMER) { |
| 2030 | host->flags &= ~SDHCI_NEEDS_RETUNING; | 2030 | host->flags &= ~SDHCI_NEEDS_RETUNING; |
| 2031 | /* Reload the new initial value for timer */ | 2031 | /* Reload the new initial value for timer */ |
| 2032 | if (host->tuning_mode == SDHCI_TUNING_MODE_1) | 2032 | mod_timer(&host->tuning_timer, jiffies + |
| 2033 | mod_timer(&host->tuning_timer, jiffies + | 2033 | host->tuning_count * HZ); |
| 2034 | host->tuning_count * HZ); | ||
| 2035 | } | 2034 | } |
| 2036 | 2035 | ||
| 2037 | /* | 2036 | /* |
| @@ -2434,9 +2433,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) | |||
| 2434 | 2433 | ||
| 2435 | if (host->runtime_suspended) { | 2434 | if (host->runtime_suspended) { |
| 2436 | spin_unlock(&host->lock); | 2435 | spin_unlock(&host->lock); |
| 2437 | pr_warning("%s: got irq while runtime suspended\n", | 2436 | return IRQ_NONE; |
| 2438 | mmc_hostname(host->mmc)); | ||
| 2439 | return IRQ_HANDLED; | ||
| 2440 | } | 2437 | } |
| 2441 | 2438 | ||
| 2442 | intmask = sdhci_readl(host, SDHCI_INT_STATUS); | 2439 | intmask = sdhci_readl(host, SDHCI_INT_STATUS); |
| @@ -2941,7 +2938,7 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 2941 | if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) | 2938 | if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) |
| 2942 | host->timeout_clk = mmc->f_max / 1000; | 2939 | host->timeout_clk = mmc->f_max / 1000; |
| 2943 | 2940 | ||
| 2944 | mmc->max_discard_to = (1 << 27) / host->timeout_clk; | 2941 | mmc->max_busy_timeout = (1 << 27) / host->timeout_clk; |
| 2945 | 2942 | ||
| 2946 | mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; | 2943 | mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; |
| 2947 | 2944 | ||
| @@ -3020,7 +3017,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 3020 | } else if (caps[1] & SDHCI_SUPPORT_SDR50) | 3017 | } else if (caps[1] & SDHCI_SUPPORT_SDR50) |
| 3021 | mmc->caps |= MMC_CAP_UHS_SDR50; | 3018 | mmc->caps |= MMC_CAP_UHS_SDR50; |
| 3022 | 3019 | ||
| 3023 | if (caps[1] & SDHCI_SUPPORT_DDR50) | 3020 | if ((caps[1] & SDHCI_SUPPORT_DDR50) && |
| 3021 | !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) | ||
| 3024 | mmc->caps |= MMC_CAP_UHS_DDR50; | 3022 | mmc->caps |= MMC_CAP_UHS_DDR50; |
| 3025 | 3023 | ||
| 3026 | /* Does the host need tuning for SDR50? */ | 3024 | /* Does the host need tuning for SDR50? */ |
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index 2d6ce257a273..91058dabd11a 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c | |||
| @@ -37,6 +37,8 @@ | |||
| 37 | 37 | ||
| 38 | struct sh_mobile_sdhi_of_data { | 38 | struct sh_mobile_sdhi_of_data { |
| 39 | unsigned long tmio_flags; | 39 | unsigned long tmio_flags; |
| 40 | unsigned long capabilities; | ||
| 41 | unsigned long capabilities2; | ||
| 40 | }; | 42 | }; |
| 41 | 43 | ||
| 42 | static const struct sh_mobile_sdhi_of_data sh_mobile_sdhi_of_cfg[] = { | 44 | static const struct sh_mobile_sdhi_of_data sh_mobile_sdhi_of_cfg[] = { |
| @@ -45,6 +47,31 @@ static const struct sh_mobile_sdhi_of_data sh_mobile_sdhi_of_cfg[] = { | |||
| 45 | }, | 47 | }, |
| 46 | }; | 48 | }; |
| 47 | 49 | ||
| 50 | static const struct sh_mobile_sdhi_of_data of_rcar_gen1_compatible = { | ||
| 51 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE, | ||
| 52 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, | ||
| 53 | }; | ||
| 54 | |||
| 55 | static const struct sh_mobile_sdhi_of_data of_rcar_gen2_compatible = { | ||
| 56 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE, | ||
| 57 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, | ||
| 58 | .capabilities2 = MMC_CAP2_NO_MULTI_READ, | ||
| 59 | }; | ||
| 60 | |||
| 61 | static const struct of_device_id sh_mobile_sdhi_of_match[] = { | ||
| 62 | { .compatible = "renesas,sdhi-shmobile" }, | ||
| 63 | { .compatible = "renesas,sdhi-sh7372" }, | ||
| 64 | { .compatible = "renesas,sdhi-sh73a0", .data = &sh_mobile_sdhi_of_cfg[0], }, | ||
| 65 | { .compatible = "renesas,sdhi-r8a73a4", .data = &sh_mobile_sdhi_of_cfg[0], }, | ||
| 66 | { .compatible = "renesas,sdhi-r8a7740", .data = &sh_mobile_sdhi_of_cfg[0], }, | ||
| 67 | { .compatible = "renesas,sdhi-r8a7778", .data = &of_rcar_gen1_compatible, }, | ||
| 68 | { .compatible = "renesas,sdhi-r8a7779", .data = &of_rcar_gen1_compatible, }, | ||
| 69 | { .compatible = "renesas,sdhi-r8a7790", .data = &of_rcar_gen2_compatible, }, | ||
| 70 | { .compatible = "renesas,sdhi-r8a7791", .data = &of_rcar_gen2_compatible, }, | ||
| 71 | {}, | ||
| 72 | }; | ||
| 73 | MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); | ||
| 74 | |||
| 48 | struct sh_mobile_sdhi { | 75 | struct sh_mobile_sdhi { |
| 49 | struct clk *clk; | 76 | struct clk *clk; |
| 50 | struct tmio_mmc_data mmc_data; | 77 | struct tmio_mmc_data mmc_data; |
| @@ -114,19 +141,6 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = { | |||
| 114 | .cd_wakeup = sh_mobile_sdhi_cd_wakeup, | 141 | .cd_wakeup = sh_mobile_sdhi_cd_wakeup, |
| 115 | }; | 142 | }; |
| 116 | 143 | ||
| 117 | static const struct of_device_id sh_mobile_sdhi_of_match[] = { | ||
| 118 | { .compatible = "renesas,sdhi-shmobile" }, | ||
| 119 | { .compatible = "renesas,sdhi-sh7372" }, | ||
| 120 | { .compatible = "renesas,sdhi-sh73a0", .data = &sh_mobile_sdhi_of_cfg[0], }, | ||
| 121 | { .compatible = "renesas,sdhi-r8a73a4", .data = &sh_mobile_sdhi_of_cfg[0], }, | ||
| 122 | { .compatible = "renesas,sdhi-r8a7740", .data = &sh_mobile_sdhi_of_cfg[0], }, | ||
| 123 | { .compatible = "renesas,sdhi-r8a7778", .data = &sh_mobile_sdhi_of_cfg[0], }, | ||
| 124 | { .compatible = "renesas,sdhi-r8a7779", .data = &sh_mobile_sdhi_of_cfg[0], }, | ||
| 125 | { .compatible = "renesas,sdhi-r8a7790", .data = &sh_mobile_sdhi_of_cfg[0], }, | ||
| 126 | {}, | ||
| 127 | }; | ||
| 128 | MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); | ||
| 129 | |||
| 130 | static int sh_mobile_sdhi_probe(struct platform_device *pdev) | 144 | static int sh_mobile_sdhi_probe(struct platform_device *pdev) |
| 131 | { | 145 | { |
| 132 | const struct of_device_id *of_id = | 146 | const struct of_device_id *of_id = |
| @@ -212,6 +226,8 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 212 | if (of_id && of_id->data) { | 226 | if (of_id && of_id->data) { |
| 213 | const struct sh_mobile_sdhi_of_data *of_data = of_id->data; | 227 | const struct sh_mobile_sdhi_of_data *of_data = of_id->data; |
| 214 | mmc_data->flags |= of_data->tmio_flags; | 228 | mmc_data->flags |= of_data->tmio_flags; |
| 229 | mmc_data->capabilities |= of_data->capabilities; | ||
| 230 | mmc_data->capabilities2 |= of_data->capabilities2; | ||
| 215 | } | 231 | } |
| 216 | 232 | ||
| 217 | /* SD control register space size is 0x100, 0x200 for bus_shift=1 */ | 233 | /* SD control register space size is 0x100, 0x200 for bus_shift=1 */ |
| @@ -316,10 +332,10 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev) | |||
| 316 | } | 332 | } |
| 317 | 333 | ||
| 318 | static const struct dev_pm_ops tmio_mmc_dev_pm_ops = { | 334 | static const struct dev_pm_ops tmio_mmc_dev_pm_ops = { |
| 319 | .suspend = tmio_mmc_host_suspend, | 335 | SET_SYSTEM_SLEEP_PM_OPS(tmio_mmc_host_suspend, tmio_mmc_host_resume) |
| 320 | .resume = tmio_mmc_host_resume, | 336 | SET_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend, |
| 321 | .runtime_suspend = tmio_mmc_host_runtime_suspend, | 337 | tmio_mmc_host_runtime_resume, |
| 322 | .runtime_resume = tmio_mmc_host_runtime_resume, | 338 | NULL) |
| 323 | }; | 339 | }; |
| 324 | 340 | ||
| 325 | static struct platform_driver sh_mobile_sdhi_driver = { | 341 | static struct platform_driver sh_mobile_sdhi_driver = { |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 1900abb04236..cfad844730d8 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
| @@ -23,38 +23,37 @@ | |||
| 23 | 23 | ||
| 24 | #include "tmio_mmc.h" | 24 | #include "tmio_mmc.h" |
| 25 | 25 | ||
| 26 | #ifdef CONFIG_PM | 26 | #ifdef CONFIG_PM_SLEEP |
| 27 | static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) | 27 | static int tmio_mmc_suspend(struct device *dev) |
| 28 | { | 28 | { |
| 29 | const struct mfd_cell *cell = mfd_get_cell(dev); | 29 | struct platform_device *pdev = to_platform_device(dev); |
| 30 | const struct mfd_cell *cell = mfd_get_cell(pdev); | ||
| 30 | int ret; | 31 | int ret; |
| 31 | 32 | ||
| 32 | ret = tmio_mmc_host_suspend(&dev->dev); | 33 | ret = tmio_mmc_host_suspend(dev); |
| 33 | 34 | ||
| 34 | /* Tell MFD core it can disable us now.*/ | 35 | /* Tell MFD core it can disable us now.*/ |
| 35 | if (!ret && cell->disable) | 36 | if (!ret && cell->disable) |
| 36 | cell->disable(dev); | 37 | cell->disable(pdev); |
| 37 | 38 | ||
| 38 | return ret; | 39 | return ret; |
| 39 | } | 40 | } |
| 40 | 41 | ||
| 41 | static int tmio_mmc_resume(struct platform_device *dev) | 42 | static int tmio_mmc_resume(struct device *dev) |
| 42 | { | 43 | { |
| 43 | const struct mfd_cell *cell = mfd_get_cell(dev); | 44 | struct platform_device *pdev = to_platform_device(dev); |
| 45 | const struct mfd_cell *cell = mfd_get_cell(pdev); | ||
| 44 | int ret = 0; | 46 | int ret = 0; |
| 45 | 47 | ||
| 46 | /* Tell the MFD core we are ready to be enabled */ | 48 | /* Tell the MFD core we are ready to be enabled */ |
| 47 | if (cell->resume) | 49 | if (cell->resume) |
| 48 | ret = cell->resume(dev); | 50 | ret = cell->resume(pdev); |
| 49 | 51 | ||
| 50 | if (!ret) | 52 | if (!ret) |
| 51 | ret = tmio_mmc_host_resume(&dev->dev); | 53 | ret = tmio_mmc_host_resume(dev); |
| 52 | 54 | ||
| 53 | return ret; | 55 | return ret; |
| 54 | } | 56 | } |
| 55 | #else | ||
| 56 | #define tmio_mmc_suspend NULL | ||
| 57 | #define tmio_mmc_resume NULL | ||
| 58 | #endif | 57 | #endif |
| 59 | 58 | ||
| 60 | static int tmio_mmc_probe(struct platform_device *pdev) | 59 | static int tmio_mmc_probe(struct platform_device *pdev) |
| @@ -134,15 +133,18 @@ static int tmio_mmc_remove(struct platform_device *pdev) | |||
| 134 | 133 | ||
| 135 | /* ------------------- device registration ----------------------- */ | 134 | /* ------------------- device registration ----------------------- */ |
| 136 | 135 | ||
| 136 | static const struct dev_pm_ops tmio_mmc_dev_pm_ops = { | ||
| 137 | SET_SYSTEM_SLEEP_PM_OPS(tmio_mmc_suspend, tmio_mmc_resume) | ||
| 138 | }; | ||
| 139 | |||
| 137 | static struct platform_driver tmio_mmc_driver = { | 140 | static struct platform_driver tmio_mmc_driver = { |
| 138 | .driver = { | 141 | .driver = { |
| 139 | .name = "tmio-mmc", | 142 | .name = "tmio-mmc", |
| 140 | .owner = THIS_MODULE, | 143 | .owner = THIS_MODULE, |
| 144 | .pm = &tmio_mmc_dev_pm_ops, | ||
| 141 | }, | 145 | }, |
| 142 | .probe = tmio_mmc_probe, | 146 | .probe = tmio_mmc_probe, |
| 143 | .remove = tmio_mmc_remove, | 147 | .remove = tmio_mmc_remove, |
| 144 | .suspend = tmio_mmc_suspend, | ||
| 145 | .resume = tmio_mmc_resume, | ||
| 146 | }; | 148 | }; |
| 147 | 149 | ||
| 148 | module_platform_driver(tmio_mmc_driver); | 150 | module_platform_driver(tmio_mmc_driver); |
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index aaa9c7e9e730..100ffe0b2faf 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h | |||
| @@ -162,16 +162,15 @@ static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host) | |||
| 162 | } | 162 | } |
| 163 | #endif | 163 | #endif |
| 164 | 164 | ||
| 165 | #ifdef CONFIG_PM | 165 | #ifdef CONFIG_PM_SLEEP |
| 166 | int tmio_mmc_host_suspend(struct device *dev); | 166 | int tmio_mmc_host_suspend(struct device *dev); |
| 167 | int tmio_mmc_host_resume(struct device *dev); | 167 | int tmio_mmc_host_resume(struct device *dev); |
| 168 | #else | ||
| 169 | #define tmio_mmc_host_suspend NULL | ||
| 170 | #define tmio_mmc_host_resume NULL | ||
| 171 | #endif | 168 | #endif |
| 172 | 169 | ||
| 170 | #ifdef CONFIG_PM_RUNTIME | ||
| 173 | int tmio_mmc_host_runtime_suspend(struct device *dev); | 171 | int tmio_mmc_host_runtime_suspend(struct device *dev); |
| 174 | int tmio_mmc_host_runtime_resume(struct device *dev); | 172 | int tmio_mmc_host_runtime_resume(struct device *dev); |
| 173 | #endif | ||
| 175 | 174 | ||
| 176 | static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) | 175 | static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) |
| 177 | { | 176 | { |
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 8d8abf23a611..faf0924e71cb 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
| @@ -1142,7 +1142,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) | |||
| 1142 | } | 1142 | } |
| 1143 | EXPORT_SYMBOL(tmio_mmc_host_remove); | 1143 | EXPORT_SYMBOL(tmio_mmc_host_remove); |
| 1144 | 1144 | ||
| 1145 | #ifdef CONFIG_PM | 1145 | #ifdef CONFIG_PM_SLEEP |
| 1146 | int tmio_mmc_host_suspend(struct device *dev) | 1146 | int tmio_mmc_host_suspend(struct device *dev) |
| 1147 | { | 1147 | { |
| 1148 | struct mmc_host *mmc = dev_get_drvdata(dev); | 1148 | struct mmc_host *mmc = dev_get_drvdata(dev); |
| @@ -1165,9 +1165,9 @@ int tmio_mmc_host_resume(struct device *dev) | |||
| 1165 | return 0; | 1165 | return 0; |
| 1166 | } | 1166 | } |
| 1167 | EXPORT_SYMBOL(tmio_mmc_host_resume); | 1167 | EXPORT_SYMBOL(tmio_mmc_host_resume); |
| 1168 | #endif | ||
| 1168 | 1169 | ||
| 1169 | #endif /* CONFIG_PM */ | 1170 | #ifdef CONFIG_PM_RUNTIME |
| 1170 | |||
| 1171 | int tmio_mmc_host_runtime_suspend(struct device *dev) | 1171 | int tmio_mmc_host_runtime_suspend(struct device *dev) |
| 1172 | { | 1172 | { |
| 1173 | return 0; | 1173 | return 0; |
| @@ -1184,5 +1184,6 @@ int tmio_mmc_host_runtime_resume(struct device *dev) | |||
| 1184 | return 0; | 1184 | return 0; |
| 1185 | } | 1185 | } |
| 1186 | EXPORT_SYMBOL(tmio_mmc_host_runtime_resume); | 1186 | EXPORT_SYMBOL(tmio_mmc_host_runtime_resume); |
| 1187 | #endif | ||
| 1187 | 1188 | ||
| 1188 | MODULE_LICENSE("GPL v2"); | 1189 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/mmc/host/ushc.c b/drivers/mmc/host/ushc.c index c0105a2e269a..d2c386f09d69 100644 --- a/drivers/mmc/host/ushc.c +++ b/drivers/mmc/host/ushc.c | |||
| @@ -504,7 +504,7 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 504 | ret = -ENOMEM; | 504 | ret = -ENOMEM; |
| 505 | goto err; | 505 | goto err; |
| 506 | } | 506 | } |
| 507 | ushc->csw = kzalloc(sizeof(struct ushc_cbw), GFP_KERNEL); | 507 | ushc->csw = kzalloc(sizeof(struct ushc_csw), GFP_KERNEL); |
| 508 | if (ushc->csw == NULL) { | 508 | if (ushc->csw == NULL) { |
| 509 | ret = -ENOMEM; | 509 | ret = -ENOMEM; |
| 510 | goto err; | 510 | goto err; |
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index e902ed7846b0..498d1f799085 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c | |||
| @@ -757,7 +757,7 @@ static int wmt_mci_probe(struct platform_device *pdev) | |||
| 757 | struct device_node *np = pdev->dev.of_node; | 757 | struct device_node *np = pdev->dev.of_node; |
| 758 | const struct of_device_id *of_id = | 758 | const struct of_device_id *of_id = |
| 759 | of_match_device(wmt_mci_dt_ids, &pdev->dev); | 759 | of_match_device(wmt_mci_dt_ids, &pdev->dev); |
| 760 | const struct wmt_mci_caps *wmt_caps = of_id->data; | 760 | const struct wmt_mci_caps *wmt_caps; |
| 761 | int ret; | 761 | int ret; |
| 762 | int regular_irq, dma_irq; | 762 | int regular_irq, dma_irq; |
| 763 | 763 | ||
| @@ -766,6 +766,8 @@ static int wmt_mci_probe(struct platform_device *pdev) | |||
| 766 | return -EFAULT; | 766 | return -EFAULT; |
| 767 | } | 767 | } |
| 768 | 768 | ||
| 769 | wmt_caps = of_id->data; | ||
| 770 | |||
| 769 | if (!np) { | 771 | if (!np) { |
| 770 | dev_err(&pdev->dev, "Missing SDMMC description in devicetree\n"); | 772 | dev_err(&pdev->dev, "Missing SDMMC description in devicetree\n"); |
| 771 | return -EFAULT; | 773 | return -EFAULT; |
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 1cd8584a7b88..903eb37f047a 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
| @@ -392,6 +392,15 @@ config REGULATOR_PALMAS | |||
| 392 | on the muxing. This is handled automatically in the driver by | 392 | on the muxing. This is handled automatically in the driver by |
| 393 | reading the mux info from OTP. | 393 | reading the mux info from OTP. |
| 394 | 394 | ||
| 395 | config REGULATOR_PBIAS | ||
| 396 | tristate "PBIAS OMAP regulator driver" | ||
| 397 | depends on (ARCH_OMAP || COMPILE_TEST) && MFD_SYSCON | ||
| 398 | help | ||
| 399 | Say y here to support pbias regulator for mmc1:SD card i/o | ||
| 400 | on OMAP SoCs. | ||
| 401 | This driver provides support for OMAP pbias modelled | ||
| 402 | regulators. | ||
| 403 | |||
| 395 | config REGULATOR_PCAP | 404 | config REGULATOR_PCAP |
| 396 | tristate "Motorola PCAP2 regulator driver" | 405 | tristate "Motorola PCAP2 regulator driver" |
| 397 | depends on EZX_PCAP | 406 | depends on EZX_PCAP |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index f0fe0c50b59c..12ef277a48b4 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
| @@ -55,6 +55,7 @@ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o | |||
| 55 | obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o | 55 | obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o |
| 56 | obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o | 56 | obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o |
| 57 | obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o | 57 | obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o |
| 58 | obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o | ||
| 58 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o | 59 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o |
| 59 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o | 60 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o |
| 60 | obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o | 61 | obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o |
diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c new file mode 100644 index 000000000000..ded3b3574209 --- /dev/null +++ b/drivers/regulator/pbias-regulator.c | |||
| @@ -0,0 +1,255 @@ | |||
| 1 | /* | ||
| 2 | * pbias-regulator.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ | ||
| 5 | * Author: Balaji T K <balajitk@ti.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License as | ||
| 9 | * published by the Free Software Foundation version 2. | ||
| 10 | * | ||
| 11 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 12 | * kind, whether express or implied; without even the implied warranty | ||
| 13 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/err.h> | ||
| 18 | #include <linux/io.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/mfd/syscon.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/regulator/driver.h> | ||
| 23 | #include <linux/regulator/machine.h> | ||
| 24 | #include <linux/regulator/of_regulator.h> | ||
| 25 | #include <linux/regmap.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | #include <linux/of.h> | ||
| 28 | #include <linux/of_device.h> | ||
| 29 | |||
| 30 | struct pbias_reg_info { | ||
| 31 | u32 enable; | ||
| 32 | u32 enable_mask; | ||
| 33 | u32 vmode; | ||
| 34 | unsigned int enable_time; | ||
| 35 | char *name; | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct pbias_regulator_data { | ||
| 39 | struct regulator_desc desc; | ||
| 40 | void __iomem *pbias_addr; | ||
| 41 | unsigned int pbias_reg; | ||
| 42 | struct regulator_dev *dev; | ||
| 43 | struct regmap *syscon; | ||
| 44 | const struct pbias_reg_info *info; | ||
| 45 | int voltage; | ||
| 46 | }; | ||
| 47 | |||
| 48 | static int pbias_regulator_set_voltage(struct regulator_dev *dev, | ||
| 49 | int min_uV, int max_uV, unsigned *selector) | ||
| 50 | { | ||
| 51 | struct pbias_regulator_data *data = rdev_get_drvdata(dev); | ||
| 52 | const struct pbias_reg_info *info = data->info; | ||
| 53 | int ret, vmode; | ||
| 54 | |||
| 55 | if (min_uV <= 1800000) | ||
| 56 | vmode = 0; | ||
| 57 | else if (min_uV > 1800000) | ||
| 58 | vmode = info->vmode; | ||
| 59 | |||
| 60 | ret = regmap_update_bits(data->syscon, data->pbias_reg, | ||
| 61 | info->vmode, vmode); | ||
| 62 | |||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | |||
| 66 | static int pbias_regulator_get_voltage(struct regulator_dev *rdev) | ||
| 67 | { | ||
| 68 | struct pbias_regulator_data *data = rdev_get_drvdata(rdev); | ||
| 69 | const struct pbias_reg_info *info = data->info; | ||
| 70 | int value, voltage; | ||
| 71 | |||
| 72 | regmap_read(data->syscon, data->pbias_reg, &value); | ||
| 73 | value &= info->vmode; | ||
| 74 | |||
| 75 | voltage = value ? 3000000 : 1800000; | ||
| 76 | |||
| 77 | return voltage; | ||
| 78 | } | ||
| 79 | |||
| 80 | static int pbias_regulator_enable(struct regulator_dev *rdev) | ||
| 81 | { | ||
| 82 | struct pbias_regulator_data *data = rdev_get_drvdata(rdev); | ||
| 83 | const struct pbias_reg_info *info = data->info; | ||
| 84 | int ret; | ||
| 85 | |||
| 86 | ret = regmap_update_bits(data->syscon, data->pbias_reg, | ||
| 87 | info->enable_mask, info->enable); | ||
| 88 | |||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 92 | static int pbias_regulator_disable(struct regulator_dev *rdev) | ||
| 93 | { | ||
| 94 | struct pbias_regulator_data *data = rdev_get_drvdata(rdev); | ||
| 95 | const struct pbias_reg_info *info = data->info; | ||
| 96 | int ret; | ||
| 97 | |||
| 98 | ret = regmap_update_bits(data->syscon, data->pbias_reg, | ||
| 99 | info->enable_mask, 0); | ||
| 100 | return ret; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int pbias_regulator_is_enable(struct regulator_dev *rdev) | ||
| 104 | { | ||
| 105 | struct pbias_regulator_data *data = rdev_get_drvdata(rdev); | ||
| 106 | const struct pbias_reg_info *info = data->info; | ||
| 107 | int value; | ||
| 108 | |||
| 109 | regmap_read(data->syscon, data->pbias_reg, &value); | ||
| 110 | |||
| 111 | return (value & info->enable_mask) == info->enable_mask; | ||
| 112 | } | ||
| 113 | |||
| 114 | static struct regulator_ops pbias_regulator_voltage_ops = { | ||
| 115 | .set_voltage = pbias_regulator_set_voltage, | ||
| 116 | .get_voltage = pbias_regulator_get_voltage, | ||
| 117 | .enable = pbias_regulator_enable, | ||
| 118 | .disable = pbias_regulator_disable, | ||
| 119 | .is_enabled = pbias_regulator_is_enable, | ||
| 120 | }; | ||
| 121 | |||
| 122 | static const struct pbias_reg_info pbias_mmc_omap2430 = { | ||
| 123 | .enable = BIT(1), | ||
| 124 | .enable_mask = BIT(1), | ||
| 125 | .vmode = BIT(0), | ||
| 126 | .enable_time = 100, | ||
| 127 | .name = "pbias_mmc_omap2430" | ||
| 128 | }; | ||
| 129 | |||
| 130 | static const struct pbias_reg_info pbias_sim_omap3 = { | ||
| 131 | .enable = BIT(9), | ||
| 132 | .enable_mask = BIT(9), | ||
| 133 | .vmode = BIT(8), | ||
| 134 | .enable_time = 100, | ||
| 135 | .name = "pbias_sim_omap3" | ||
| 136 | }; | ||
| 137 | |||
| 138 | static const struct pbias_reg_info pbias_mmc_omap4 = { | ||
| 139 | .enable = BIT(26) | BIT(22), | ||
| 140 | .enable_mask = BIT(26) | BIT(25) | BIT(22), | ||
| 141 | .vmode = BIT(21), | ||
| 142 | .enable_time = 100, | ||
| 143 | .name = "pbias_mmc_omap4" | ||
| 144 | }; | ||
| 145 | |||
| 146 | static const struct pbias_reg_info pbias_mmc_omap5 = { | ||
| 147 | .enable = BIT(27) | BIT(26), | ||
| 148 | .enable_mask = BIT(27) | BIT(25) | BIT(26), | ||
| 149 | .vmode = BIT(21), | ||
| 150 | .enable_time = 100, | ||
| 151 | .name = "pbias_mmc_omap5" | ||
| 152 | }; | ||
| 153 | |||
| 154 | static struct of_regulator_match pbias_matches[] = { | ||
| 155 | { .name = "pbias_mmc_omap2430", .driver_data = (void *)&pbias_mmc_omap2430}, | ||
| 156 | { .name = "pbias_sim_omap3", .driver_data = (void *)&pbias_sim_omap3}, | ||
| 157 | { .name = "pbias_mmc_omap4", .driver_data = (void *)&pbias_mmc_omap4}, | ||
| 158 | { .name = "pbias_mmc_omap5", .driver_data = (void *)&pbias_mmc_omap5}, | ||
| 159 | }; | ||
| 160 | #define PBIAS_NUM_REGS ARRAY_SIZE(pbias_matches) | ||
| 161 | |||
| 162 | static const struct of_device_id pbias_of_match[] = { | ||
| 163 | { .compatible = "ti,pbias-omap", }, | ||
| 164 | {}, | ||
| 165 | }; | ||
| 166 | MODULE_DEVICE_TABLE(of, pbias_of_match); | ||
| 167 | |||
| 168 | static int pbias_regulator_probe(struct platform_device *pdev) | ||
| 169 | { | ||
| 170 | struct device_node *np = pdev->dev.of_node; | ||
| 171 | struct pbias_regulator_data *drvdata; | ||
| 172 | struct resource *res; | ||
| 173 | struct regulator_config cfg = { }; | ||
| 174 | struct regmap *syscon; | ||
| 175 | const struct pbias_reg_info *info; | ||
| 176 | int ret = 0; | ||
| 177 | int count, idx, data_idx = 0; | ||
| 178 | |||
| 179 | count = of_regulator_match(&pdev->dev, np, pbias_matches, | ||
| 180 | PBIAS_NUM_REGS); | ||
| 181 | if (count < 0) | ||
| 182 | return count; | ||
| 183 | |||
| 184 | drvdata = devm_kzalloc(&pdev->dev, sizeof(struct pbias_regulator_data) | ||
| 185 | * count, GFP_KERNEL); | ||
| 186 | if (drvdata == NULL) { | ||
| 187 | dev_err(&pdev->dev, "Failed to allocate device data\n"); | ||
| 188 | return -ENOMEM; | ||
| 189 | } | ||
| 190 | |||
| 191 | syscon = syscon_regmap_lookup_by_phandle(np, "syscon"); | ||
| 192 | if (IS_ERR(syscon)) | ||
| 193 | return PTR_ERR(syscon); | ||
| 194 | |||
| 195 | cfg.dev = &pdev->dev; | ||
| 196 | |||
| 197 | for (idx = 0; idx < PBIAS_NUM_REGS && data_idx < count; idx++) { | ||
| 198 | if (!pbias_matches[idx].init_data || | ||
| 199 | !pbias_matches[idx].of_node) | ||
| 200 | continue; | ||
| 201 | |||
| 202 | info = pbias_matches[idx].driver_data; | ||
| 203 | if (!info) | ||
| 204 | return -ENODEV; | ||
| 205 | |||
| 206 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 207 | if (!res) | ||
| 208 | return -EINVAL; | ||
| 209 | |||
| 210 | drvdata[data_idx].pbias_reg = res->start; | ||
| 211 | drvdata[data_idx].syscon = syscon; | ||
| 212 | drvdata[data_idx].info = info; | ||
| 213 | drvdata[data_idx].desc.name = info->name; | ||
| 214 | drvdata[data_idx].desc.owner = THIS_MODULE; | ||
| 215 | drvdata[data_idx].desc.type = REGULATOR_VOLTAGE; | ||
| 216 | drvdata[data_idx].desc.ops = &pbias_regulator_voltage_ops; | ||
| 217 | drvdata[data_idx].desc.n_voltages = 2; | ||
| 218 | drvdata[data_idx].desc.enable_time = info->enable_time; | ||
| 219 | |||
| 220 | cfg.init_data = pbias_matches[idx].init_data; | ||
| 221 | cfg.driver_data = &drvdata[data_idx]; | ||
| 222 | cfg.of_node = pbias_matches[idx].of_node; | ||
| 223 | |||
| 224 | drvdata[data_idx].dev = devm_regulator_register(&pdev->dev, | ||
| 225 | &drvdata[data_idx].desc, &cfg); | ||
| 226 | if (IS_ERR(drvdata[data_idx].dev)) { | ||
| 227 | ret = PTR_ERR(drvdata[data_idx].dev); | ||
| 228 | dev_err(&pdev->dev, | ||
| 229 | "Failed to register regulator: %d\n", ret); | ||
| 230 | goto err_regulator; | ||
| 231 | } | ||
| 232 | data_idx++; | ||
| 233 | } | ||
| 234 | |||
| 235 | platform_set_drvdata(pdev, drvdata); | ||
| 236 | |||
| 237 | err_regulator: | ||
| 238 | return ret; | ||
| 239 | } | ||
| 240 | |||
| 241 | static struct platform_driver pbias_regulator_driver = { | ||
| 242 | .probe = pbias_regulator_probe, | ||
| 243 | .driver = { | ||
| 244 | .name = "pbias-regulator", | ||
| 245 | .owner = THIS_MODULE, | ||
| 246 | .of_match_table = of_match_ptr(pbias_of_match), | ||
| 247 | }, | ||
| 248 | }; | ||
| 249 | |||
| 250 | module_platform_driver(pbias_regulator_driver); | ||
| 251 | |||
| 252 | MODULE_AUTHOR("Balaji T K <balajitk@ti.com>"); | ||
| 253 | MODULE_DESCRIPTION("pbias voltage regulator"); | ||
| 254 | MODULE_LICENSE("GPL"); | ||
| 255 | MODULE_ALIAS("platform:pbias-regulator"); | ||
diff --git a/include/linux/mfd/rtsx_common.h b/include/linux/mfd/rtsx_common.h index 443176ee1ab0..7c36cc55d2c7 100644 --- a/include/linux/mfd/rtsx_common.h +++ b/include/linux/mfd/rtsx_common.h | |||
| @@ -45,6 +45,7 @@ struct platform_device; | |||
| 45 | struct rtsx_slot { | 45 | struct rtsx_slot { |
| 46 | struct platform_device *p_dev; | 46 | struct platform_device *p_dev; |
| 47 | void (*card_event)(struct platform_device *p_dev); | 47 | void (*card_event)(struct platform_device *p_dev); |
| 48 | void (*done_transfer)(struct platform_device *p_dev); | ||
| 48 | }; | 49 | }; |
| 49 | 50 | ||
| 50 | #endif | 51 | #endif |
diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 0ce772105508..8d6bbd609ad9 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h | |||
| @@ -144,7 +144,7 @@ | |||
| 144 | #define HOST_TO_DEVICE 0 | 144 | #define HOST_TO_DEVICE 0 |
| 145 | #define DEVICE_TO_HOST 1 | 145 | #define DEVICE_TO_HOST 1 |
| 146 | 146 | ||
| 147 | #define MAX_PHASE 31 | 147 | #define RTSX_PHASE_MAX 32 |
| 148 | #define RX_TUNING_CNT 3 | 148 | #define RX_TUNING_CNT 3 |
| 149 | 149 | ||
| 150 | /* SG descriptor */ | 150 | /* SG descriptor */ |
| @@ -943,6 +943,12 @@ void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr); | |||
| 943 | int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout); | 943 | int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout); |
| 944 | int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, | 944 | int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, |
| 945 | int num_sg, bool read, int timeout); | 945 | int num_sg, bool read, int timeout); |
| 946 | int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
| 947 | int num_sg, bool read); | ||
| 948 | int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
| 949 | int num_sg, bool read); | ||
| 950 | int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist, | ||
| 951 | int sg_count, bool read); | ||
| 946 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len); | 952 | int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len); |
| 947 | int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len); | 953 | int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len); |
| 948 | int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card); | 954 | int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card); |
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 87079fc38011..f206e29f94d7 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h | |||
| @@ -95,7 +95,7 @@ struct mmc_command { | |||
| 95 | * actively failing requests | 95 | * actively failing requests |
| 96 | */ | 96 | */ |
| 97 | 97 | ||
| 98 | unsigned int cmd_timeout_ms; /* in milliseconds */ | 98 | unsigned int busy_timeout; /* busy detect timeout in ms */ |
| 99 | /* Set this flag only for blocking sanitize request */ | 99 | /* Set this flag only for blocking sanitize request */ |
| 100 | bool sanitize_busy; | 100 | bool sanitize_busy; |
| 101 | 101 | ||
| @@ -152,7 +152,7 @@ extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, | |||
| 152 | struct mmc_command *, int); | 152 | struct mmc_command *, int); |
| 153 | extern void mmc_start_bkops(struct mmc_card *card, bool from_exception); | 153 | extern void mmc_start_bkops(struct mmc_card *card, bool from_exception); |
| 154 | extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool, | 154 | extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool, |
| 155 | bool); | 155 | bool, bool); |
| 156 | extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); | 156 | extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); |
| 157 | extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd); | 157 | extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd); |
| 158 | 158 | ||
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 99f5709ac343..cb61ea4d6945 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
| @@ -264,15 +264,12 @@ struct mmc_host { | |||
| 264 | u32 caps2; /* More host capabilities */ | 264 | u32 caps2; /* More host capabilities */ |
| 265 | 265 | ||
| 266 | #define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */ | 266 | #define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */ |
| 267 | #define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */ | ||
| 268 | #define MMC_CAP2_FULL_PWR_CYCLE (1 << 2) /* Can do full power cycle */ | 267 | #define MMC_CAP2_FULL_PWR_CYCLE (1 << 2) /* Can do full power cycle */ |
| 269 | #define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock reads don't work */ | 268 | #define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock reads don't work */ |
| 270 | #define MMC_CAP2_NO_SLEEP_CMD (1 << 4) /* Don't allow sleep command */ | ||
| 271 | #define MMC_CAP2_HS200_1_8V_SDR (1 << 5) /* can support */ | 269 | #define MMC_CAP2_HS200_1_8V_SDR (1 << 5) /* can support */ |
| 272 | #define MMC_CAP2_HS200_1_2V_SDR (1 << 6) /* can support */ | 270 | #define MMC_CAP2_HS200_1_2V_SDR (1 << 6) /* can support */ |
| 273 | #define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \ | 271 | #define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \ |
| 274 | MMC_CAP2_HS200_1_2V_SDR) | 272 | MMC_CAP2_HS200_1_2V_SDR) |
| 275 | #define MMC_CAP2_BROKEN_VOLTAGE (1 << 7) /* Use the broken voltage */ | ||
| 276 | #define MMC_CAP2_HC_ERASE_SZ (1 << 9) /* High-capacity erase size */ | 273 | #define MMC_CAP2_HC_ERASE_SZ (1 << 9) /* High-capacity erase size */ |
| 277 | #define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */ | 274 | #define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */ |
| 278 | #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ | 275 | #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ |
| @@ -281,7 +278,6 @@ struct mmc_host { | |||
| 281 | #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ | 278 | #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ |
| 282 | MMC_CAP2_PACKED_WR) | 279 | MMC_CAP2_PACKED_WR) |
| 283 | #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ | 280 | #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ |
| 284 | #define MMC_CAP2_SANITIZE (1 << 15) /* Support Sanitize */ | ||
| 285 | 281 | ||
| 286 | mmc_pm_flag_t pm_caps; /* supported pm features */ | 282 | mmc_pm_flag_t pm_caps; /* supported pm features */ |
| 287 | 283 | ||
| @@ -304,7 +300,7 @@ struct mmc_host { | |||
| 304 | unsigned int max_req_size; /* maximum number of bytes in one req */ | 300 | unsigned int max_req_size; /* maximum number of bytes in one req */ |
| 305 | unsigned int max_blk_size; /* maximum size of one mmc block */ | 301 | unsigned int max_blk_size; /* maximum size of one mmc block */ |
| 306 | unsigned int max_blk_count; /* maximum number of blocks in one req */ | 302 | unsigned int max_blk_count; /* maximum number of blocks in one req */ |
| 307 | unsigned int max_discard_to; /* max. discard timeout in ms */ | 303 | unsigned int max_busy_timeout; /* max busy timeout in ms */ |
| 308 | 304 | ||
| 309 | /* private data */ | 305 | /* private data */ |
| 310 | spinlock_t lock; /* lock for claim and bus ops */ | 306 | spinlock_t lock; /* lock for claim and bus ops */ |
| @@ -388,8 +384,6 @@ int mmc_power_restore_host(struct mmc_host *host); | |||
| 388 | void mmc_detect_change(struct mmc_host *, unsigned long delay); | 384 | void mmc_detect_change(struct mmc_host *, unsigned long delay); |
| 389 | void mmc_request_done(struct mmc_host *, struct mmc_request *); | 385 | void mmc_request_done(struct mmc_host *, struct mmc_request *); |
| 390 | 386 | ||
| 391 | int mmc_cache_ctrl(struct mmc_host *, u8); | ||
| 392 | |||
| 393 | static inline void mmc_signal_sdio_irq(struct mmc_host *host) | 387 | static inline void mmc_signal_sdio_irq(struct mmc_host *host) |
| 394 | { | 388 | { |
| 395 | host->ops->enable_sdio_irq(host, 0); | 389 | host->ops->enable_sdio_irq(host, 0); |
| @@ -424,12 +418,9 @@ static inline int mmc_regulator_get_supply(struct mmc_host *mmc) | |||
| 424 | 418 | ||
| 425 | int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); | 419 | int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); |
| 426 | 420 | ||
| 427 | /* Module parameter */ | ||
| 428 | extern bool mmc_assume_removable; | ||
| 429 | |||
| 430 | static inline int mmc_card_is_removable(struct mmc_host *host) | 421 | static inline int mmc_card_is_removable(struct mmc_host *host) |
| 431 | { | 422 | { |
| 432 | return !(host->caps & MMC_CAP_NONREMOVABLE) && mmc_assume_removable; | 423 | return !(host->caps & MMC_CAP_NONREMOVABLE); |
| 433 | } | 424 | } |
| 434 | 425 | ||
| 435 | static inline int mmc_card_keep_power(struct mmc_host *host) | 426 | static inline int mmc_card_keep_power(struct mmc_host *host) |
diff --git a/include/linux/mmc/sdhci-spear.h b/include/linux/mmc/sdhci-spear.h index e78c0e236e9d..8cc095a76cf8 100644 --- a/include/linux/mmc/sdhci-spear.h +++ b/include/linux/mmc/sdhci-spear.h | |||
| @@ -18,17 +18,9 @@ | |||
| 18 | /* | 18 | /* |
| 19 | * struct sdhci_plat_data: spear sdhci platform data structure | 19 | * struct sdhci_plat_data: spear sdhci platform data structure |
| 20 | * | 20 | * |
| 21 | * @card_power_gpio: gpio pin for enabling/disabling power to sdhci socket | ||
| 22 | * @power_active_high: if set, enable power to sdhci socket by setting | ||
| 23 | * card_power_gpio | ||
| 24 | * @power_always_enb: If set, then enable power on probe, otherwise enable only | ||
| 25 | * on card insertion and disable on card removal. | ||
| 26 | * card_int_gpio: gpio pin used for card detection | 21 | * card_int_gpio: gpio pin used for card detection |
| 27 | */ | 22 | */ |
| 28 | struct sdhci_plat_data { | 23 | struct sdhci_plat_data { |
| 29 | int card_power_gpio; | ||
| 30 | int power_active_high; | ||
| 31 | int power_always_enb; | ||
| 32 | int card_int_gpio; | 24 | int card_int_gpio; |
| 33 | }; | 25 | }; |
| 34 | 26 | ||
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 362927c48f97..7be12b883485 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h | |||
| @@ -100,6 +100,8 @@ struct sdhci_host { | |||
| 100 | #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) | 100 | #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) |
| 101 | /* Controller does not support HS200 */ | 101 | /* Controller does not support HS200 */ |
| 102 | #define SDHCI_QUIRK2_BROKEN_HS200 (1<<6) | 102 | #define SDHCI_QUIRK2_BROKEN_HS200 (1<<6) |
| 103 | /* Controller does not support DDR50 */ | ||
| 104 | #define SDHCI_QUIRK2_BROKEN_DDR50 (1<<7) | ||
| 103 | 105 | ||
| 104 | int irq; /* Device IRQ */ | 106 | int irq; /* Device IRQ */ |
| 105 | void __iomem *ioaddr; /* Mapped address */ | 107 | void __iomem *ioaddr; /* Mapped address */ |
diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h index b0c73e4cacea..d2433381e828 100644 --- a/include/linux/mmc/slot-gpio.h +++ b/include/linux/mmc/slot-gpio.h | |||
| @@ -22,4 +22,10 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, | |||
| 22 | unsigned int debounce); | 22 | unsigned int debounce); |
| 23 | void mmc_gpio_free_cd(struct mmc_host *host); | 23 | void mmc_gpio_free_cd(struct mmc_host *host); |
| 24 | 24 | ||
| 25 | int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, | ||
| 26 | unsigned int idx, bool override_active_level, | ||
| 27 | unsigned int debounce); | ||
| 28 | void mmc_gpiod_free_cd(struct mmc_host *host); | ||
| 29 | void mmc_gpiod_request_cd_irq(struct mmc_host *host); | ||
| 30 | |||
| 25 | #endif | 31 | #endif |
diff --git a/include/linux/platform_data/mmc-msm_sdcc.h b/include/linux/platform_data/mmc-msm_sdcc.h index ffcd9e3a6a7e..55aa873c9396 100644 --- a/include/linux/platform_data/mmc-msm_sdcc.h +++ b/include/linux/platform_data/mmc-msm_sdcc.h | |||
| @@ -1,8 +1,5 @@ | |||
| 1 | /* | 1 | #ifndef __MMC_MSM_SDCC_H |
| 2 | * arch/arm/include/asm/mach/mmc.h | 2 | #define __MMC_MSM_SDCC_H |
| 3 | */ | ||
| 4 | #ifndef ASMARM_MACH_MMC_H | ||
| 5 | #define ASMARM_MACH_MMC_H | ||
| 6 | 3 | ||
| 7 | #include <linux/mmc/host.h> | 4 | #include <linux/mmc/host.h> |
| 8 | #include <linux/mmc/card.h> | 5 | #include <linux/mmc/card.h> |
diff --git a/include/linux/platform_data/mmc-mvsdio.h b/include/linux/platform_data/mmc-mvsdio.h index 1190efedcb94..d02704cd3695 100644 --- a/include/linux/platform_data/mmc-mvsdio.h +++ b/include/linux/platform_data/mmc-mvsdio.h | |||
| @@ -1,13 +1,11 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/plat-orion/include/plat/mvsdio.h | ||
| 3 | * | ||
| 4 | * This file is licensed under the terms of the GNU General Public | 2 | * This file is licensed under the terms of the GNU General Public |
| 5 | * License version 2. This program is licensed "as is" without any | 3 | * License version 2. This program is licensed "as is" without any |
| 6 | * warranty of any kind, whether express or implied. | 4 | * warranty of any kind, whether express or implied. |
| 7 | */ | 5 | */ |
| 8 | 6 | ||
| 9 | #ifndef __MACH_MVSDIO_H | 7 | #ifndef __MMC_MVSDIO_H |
| 10 | #define __MACH_MVSDIO_H | 8 | #define __MMC_MVSDIO_H |
| 11 | 9 | ||
| 12 | #include <linux/mbus.h> | 10 | #include <linux/mbus.h> |
| 13 | 11 | ||
