diff options
55 files changed, 2277 insertions, 809 deletions
diff --git a/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt new file mode 100644 index 000000000000..0a85c70cd30a --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | * Atmel High Speed MultiMedia Card Interface | ||
| 2 | |||
| 3 | This controller on atmel products provides an interface for MMC, SD and SDIO | ||
| 4 | types of memory cards. | ||
| 5 | |||
| 6 | This file documents differences between the core properties described | ||
| 7 | by mmc.txt and the properties used by the atmel-mci driver. | ||
| 8 | |||
| 9 | 1) MCI node | ||
| 10 | |||
| 11 | Required properties: | ||
| 12 | - compatible: should be "atmel,hsmci" | ||
| 13 | - #address-cells: should be one. The cell is the slot id. | ||
| 14 | - #size-cells: should be zero. | ||
| 15 | - at least one slot node | ||
| 16 | |||
| 17 | The node contains child nodes for each slot that the platform uses | ||
| 18 | |||
| 19 | Example MCI node: | ||
| 20 | |||
| 21 | mmc0: mmc@f0008000 { | ||
| 22 | compatible = "atmel,hsmci"; | ||
| 23 | reg = <0xf0008000 0x600>; | ||
| 24 | interrupts = <12 4>; | ||
| 25 | #address-cells = <1>; | ||
| 26 | #size-cells = <0>; | ||
| 27 | |||
| 28 | [ child node definitions...] | ||
| 29 | }; | ||
| 30 | |||
| 31 | 2) slot nodes | ||
| 32 | |||
| 33 | Required properties: | ||
| 34 | - reg: should contain the slot id. | ||
| 35 | - bus-width: number of data lines connected to the controller | ||
| 36 | |||
| 37 | Optional properties: | ||
| 38 | - cd-gpios: specify GPIOs for card detection | ||
| 39 | - cd-inverted: invert the value of external card detect gpio line | ||
| 40 | - wp-gpios: specify GPIOs for write protection | ||
| 41 | |||
| 42 | Example slot node: | ||
| 43 | |||
| 44 | slot@0 { | ||
| 45 | reg = <0>; | ||
| 46 | bus-width = <4>; | ||
| 47 | cd-gpios = <&pioD 15 0> | ||
| 48 | cd-inverted; | ||
| 49 | }; | ||
| 50 | |||
| 51 | Example full MCI node: | ||
| 52 | mmc0: mmc@f0008000 { | ||
| 53 | compatible = "atmel,hsmci"; | ||
| 54 | reg = <0xf0008000 0x600>; | ||
| 55 | interrupts = <12 4>; | ||
| 56 | #address-cells = <1>; | ||
| 57 | #size-cells = <0>; | ||
| 58 | slot@0 { | ||
| 59 | reg = <0>; | ||
| 60 | bus-width = <4>; | ||
| 61 | cd-gpios = <&pioD 15 0> | ||
| 62 | cd-inverted; | ||
| 63 | }; | ||
| 64 | slot@1 { | ||
| 65 | reg = <1>; | ||
| 66 | bus-width = <4>; | ||
| 67 | }; | ||
| 68 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt new file mode 100644 index 000000000000..792768953330 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | * Samsung Exynos specific extensions to the Synopsis Designware Mobile | ||
| 2 | Storage Host Controller | ||
| 3 | |||
| 4 | The Synopsis designware mobile storage host controller is used to interface | ||
| 5 | a SoC with storage medium such as eMMC or SD/MMC cards. This file documents | ||
| 6 | differences between the core Synopsis dw mshc controller properties described | ||
| 7 | by synposis-dw-mshc.txt and the properties used by the Samsung Exynos specific | ||
| 8 | extensions to the Synopsis Designware Mobile Storage Host Controller. | ||
| 9 | |||
| 10 | Required Properties: | ||
| 11 | |||
| 12 | * compatible: should be | ||
| 13 | - "samsung,exynos4210-dw-mshc": for controllers with Samsung Exynos4210 | ||
| 14 | specific extentions. | ||
| 15 | - "samsung,exynos4412-dw-mshc": for controllers with Samsung Exynos4412 | ||
| 16 | specific extentions. | ||
| 17 | - "samsung,exynos5250-dw-mshc": for controllers with Samsung Exynos5250 | ||
| 18 | specific extentions. | ||
| 19 | |||
| 20 | * samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface | ||
| 21 | unit (ciu) clock. This property is applicable only for Exynos5 SoC's and | ||
| 22 | ignored for Exynos4 SoC's. The valid range of divider value is 0 to 7. | ||
| 23 | |||
| 24 | * samsung,dw-mshc-sdr-timing: Specifies the value of CIU clock phase shift value | ||
| 25 | in transmit mode and CIU clock phase shift value in receive mode for single | ||
| 26 | data rate mode operation. Refer notes below for the order of the cells and the | ||
| 27 | valid values. | ||
| 28 | |||
| 29 | * samsung,dw-mshc-ddr-timing: Specifies the value of CUI clock phase shift value | ||
| 30 | in transmit mode and CIU clock phase shift value in receive mode for double | ||
| 31 | data rate mode operation. Refer notes below for the order of the cells and the | ||
| 32 | valid values. | ||
| 33 | |||
| 34 | Notes for the sdr-timing and ddr-timing values: | ||
| 35 | |||
| 36 | The order of the cells should be | ||
| 37 | - First Cell: CIU clock phase shift value for tx mode. | ||
| 38 | - Second Cell: CIU clock phase shift value for rx mode. | ||
| 39 | |||
| 40 | Valid values for SDR and DDR CIU clock timing for Exynos5250: | ||
| 41 | - valid value for tx phase shift and rx phase shift is 0 to 7. | ||
| 42 | - when CIU clock divider value is set to 3, all possible 8 phase shift | ||
| 43 | values can be used. | ||
| 44 | - if CIU clock divider value is 0 (that is divide by 1), both tx and rx | ||
| 45 | phase shift clocks should be 0. | ||
| 46 | |||
| 47 | Required properties for a slot: | ||
| 48 | |||
| 49 | * gpios: specifies a list of gpios used for command, clock and data bus. The | ||
| 50 | first gpio is the command line and the second gpio is the clock line. The | ||
| 51 | rest of the gpios (depending on the bus-width property) are the data lines in | ||
| 52 | no particular order. The format of the gpio specifier depends on the gpio | ||
| 53 | controller. | ||
| 54 | |||
| 55 | Example: | ||
| 56 | |||
| 57 | The MSHC controller node can be split into two portions, SoC specific and | ||
| 58 | board specific portions as listed below. | ||
| 59 | |||
| 60 | dwmmc0@12200000 { | ||
| 61 | compatible = "samsung,exynos5250-dw-mshc"; | ||
| 62 | reg = <0x12200000 0x1000>; | ||
| 63 | interrupts = <0 75 0>; | ||
| 64 | #address-cells = <1>; | ||
| 65 | #size-cells = <0>; | ||
| 66 | }; | ||
| 67 | |||
| 68 | dwmmc0@12200000 { | ||
| 69 | num-slots = <1>; | ||
| 70 | supports-highspeed; | ||
| 71 | broken-cd; | ||
| 72 | fifo-depth = <0x80>; | ||
| 73 | card-detect-delay = <200>; | ||
| 74 | samsung,dw-mshc-ciu-div = <3>; | ||
| 75 | samsung,dw-mshc-sdr-timing = <2 3>; | ||
| 76 | samsung,dw-mshc-ddr-timing = <1 2>; | ||
| 77 | |||
| 78 | slot@0 { | ||
| 79 | reg = <0>; | ||
| 80 | bus-width = <8>; | ||
| 81 | gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>, | ||
| 82 | <&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>, | ||
| 83 | <&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>, | ||
| 84 | <&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>, | ||
| 85 | <&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>; | ||
| 86 | }; | ||
| 87 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt index 8a6811f4a02f..8e2e0ba2f486 100644 --- a/Documentation/devicetree/bindings/mmc/mmc.txt +++ b/Documentation/devicetree/bindings/mmc/mmc.txt | |||
| @@ -9,12 +9,17 @@ Interpreted by the OF core: | |||
| 9 | Required properties: | 9 | Required properties: |
| 10 | - bus-width: Number of data lines, can be <1>, <4>, or <8> | 10 | - bus-width: Number of data lines, can be <1>, <4>, or <8> |
| 11 | 11 | ||
| 12 | Card detection: | ||
| 13 | If no property below is supplied, standard SDHCI card detect is used. | ||
| 14 | Only one of the properties in this section should be supplied: | ||
| 15 | - broken-cd: There is no card detection available; polling must be used. | ||
| 16 | - cd-gpios: Specify GPIOs for card detection, see gpio binding | ||
| 17 | - non-removable: non-removable slot (like eMMC); assume always present. | ||
| 18 | |||
| 12 | Optional properties: | 19 | Optional properties: |
| 13 | - cd-gpios: Specify GPIOs for card detection, see gpio binding | ||
| 14 | - wp-gpios: Specify GPIOs for write protection, see gpio binding | 20 | - wp-gpios: Specify GPIOs for write protection, see gpio binding |
| 15 | - cd-inverted: when present, polarity on the cd gpio line is inverted | 21 | - cd-inverted: when present, polarity on the cd gpio line is inverted |
| 16 | - wp-inverted: when present, polarity on the wp gpio line is inverted | 22 | - wp-inverted: when present, polarity on the wp gpio line is inverted |
| 17 | - non-removable: non-removable slot (like eMMC) | ||
| 18 | - max-frequency: maximum operating clock frequency | 23 | - max-frequency: maximum operating clock frequency |
| 19 | 24 | ||
| 20 | Example: | 25 | Example: |
diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt new file mode 100644 index 000000000000..b7025de7dced --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | * PXA MMC drivers | ||
| 2 | |||
| 3 | Driver bindings for the PXA MCI (MMC/SDIO) interfaces | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | - compatible: Should be "marvell,pxa-mmc". | ||
| 7 | - vmmc-supply: A regulator for VMMC | ||
| 8 | |||
| 9 | Optional properties: | ||
| 10 | - marvell,detect-delay-ms: sets the detection delay timeout in ms. | ||
| 11 | - marvell,gpio-power: GPIO spec for the card power enable pin | ||
| 12 | |||
| 13 | This file documents differences between the core properties in mmc.txt | ||
| 14 | and the properties used by the pxa-mmc driver. | ||
| 15 | |||
| 16 | Examples: | ||
| 17 | |||
| 18 | mmc0: mmc@41100000 { | ||
| 19 | compatible = "marvell,pxa-mmc"; | ||
| 20 | reg = <0x41100000 0x1000>; | ||
| 21 | interrupts = <23>; | ||
| 22 | cd-gpios = <&gpio 23 0>; | ||
| 23 | wp-gpios = <&gpio 24 0>; | ||
| 24 | }; | ||
| 25 | |||
diff --git a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt new file mode 100644 index 000000000000..630a7d7f4718 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | * Samsung's SDHCI Controller device tree bindings | ||
| 2 | |||
| 3 | Samsung's SDHCI controller is used as a connectivity interface with external | ||
| 4 | MMC, SD and eMMC storage mediums. This file documents differences between the | ||
| 5 | core mmc properties described by mmc.txt and the properties used by the | ||
| 6 | Samsung implmentation of the SDHCI controller. | ||
| 7 | |||
| 8 | Note: The mmc core bindings documentation states that if none of the core | ||
| 9 | card-detect bindings are used, then the standard sdhci card detect mechanism | ||
| 10 | is used. The Samsung's SDHCI controller bindings extends this as listed below. | ||
| 11 | |||
| 12 | [A] The property "samsung,cd-pinmux-gpio" can be used as stated in the | ||
| 13 | "Optional Board Specific Properties" section below. | ||
| 14 | |||
| 15 | [B] If core card-detect bindings and "samsung,cd-pinmux-gpio" property | ||
| 16 | is not specified, it is assumed that there is no card detection | ||
| 17 | mechanism used. | ||
| 18 | |||
| 19 | Required SoC Specific Properties: | ||
| 20 | - compatible: should be one of the following | ||
| 21 | - "samsung,s3c6410-sdhci": For controllers compatible with s3c6410 sdhci | ||
| 22 | controller. | ||
| 23 | - "samsung,exynos4210-sdhci": For controllers compatible with Exynos4 sdhci | ||
| 24 | controller. | ||
| 25 | |||
| 26 | Required Board Specific Properties: | ||
| 27 | - gpios: Should specify the gpios used for clock, command and data lines. The | ||
| 28 | gpio specifier format depends on the gpio controller. | ||
| 29 | |||
| 30 | Optional Board Specific Properties: | ||
| 31 | - samsung,cd-pinmux-gpio: Specifies the card detect line that is routed | ||
| 32 | through a pinmux to the card-detect pin of the card slot. This property | ||
| 33 | should be used only if none of the mmc core card-detect properties are | ||
| 34 | used. | ||
| 35 | |||
| 36 | Example: | ||
| 37 | sdhci@12530000 { | ||
| 38 | compatible = "samsung,exynos4210-sdhci"; | ||
| 39 | reg = <0x12530000 0x100>; | ||
| 40 | interrupts = <0 75 0>; | ||
| 41 | bus-width = <4>; | ||
| 42 | cd-gpios = <&gpk2 2 2 3 3>; | ||
| 43 | gpios = <&gpk2 0 2 0 3>, /* clock line */ | ||
| 44 | <&gpk2 1 2 0 3>, /* command line */ | ||
| 45 | <&gpk2 3 2 3 3>, /* data line 0 */ | ||
| 46 | <&gpk2 4 2 3 3>, /* data line 1 */ | ||
| 47 | <&gpk2 5 2 3 3>, /* data line 2 */ | ||
| 48 | <&gpk2 6 2 3 3>; /* data line 3 */ | ||
| 49 | }; | ||
| 50 | |||
| 51 | Note: This example shows both SoC specific and board specific properties | ||
| 52 | in a single device node. The properties can be actually be seperated | ||
| 53 | into SoC specific node and board specific node. | ||
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-dove.txt b/Documentation/devicetree/bindings/mmc/sdhci-dove.txt new file mode 100644 index 000000000000..ae9aab9abcd7 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/sdhci-dove.txt | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | * Marvell sdhci-dove controller | ||
| 2 | |||
| 3 | This file documents differences between the core properties in mmc.txt | ||
| 4 | and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers. | ||
| 5 | |||
| 6 | - compatible: Should be "marvell,dove-sdhci". | ||
| 7 | |||
| 8 | Example: | ||
| 9 | |||
| 10 | sdio0: sdio@92000 { | ||
| 11 | compatible = "marvell,dove-sdhci"; | ||
| 12 | reg = <0x92000 0x100>; | ||
| 13 | interrupts = <35>; | ||
| 14 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-spear.txt b/Documentation/devicetree/bindings/mmc/sdhci-spear.txt new file mode 100644 index 000000000000..fd3643e7e467 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/sdhci-spear.txt | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | * SPEAr SDHCI Controller | ||
| 2 | |||
| 3 | This file documents differences between the core properties in mmc.txt | ||
| 4 | and the properties used by the sdhci-spear driver. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | - compatible: "st,spear300-sdhci" | ||
| 8 | |||
| 9 | Optional properties: | ||
| 10 | - cd-gpios: card detect gpio, with zero flags. | ||
| 11 | |||
| 12 | Example: | ||
| 13 | |||
| 14 | sdhci@fc000000 { | ||
| 15 | compatible = "st,spear300-sdhci"; | ||
| 16 | reg = <0xfc000000 0x1000>; | ||
| 17 | cd-gpios = <&gpio0 6 0>; | ||
| 18 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt new file mode 100644 index 000000000000..06cd32d08052 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | * Synopsis Designware Mobile Storage Host Controller | ||
| 2 | |||
| 3 | The Synopsis designware mobile storage host controller is used to interface | ||
| 4 | a SoC with storage medium such as eMMC or SD/MMC cards. This file documents | ||
| 5 | differences between the core mmc properties described by mmc.txt and the | ||
| 6 | properties used by the Synopsis Designware Mobile Storage Host Controller. | ||
| 7 | |||
| 8 | Required Properties: | ||
| 9 | |||
| 10 | * compatible: should be | ||
| 11 | - snps,dw-mshc: for controllers compliant with synopsis dw-mshc. | ||
| 12 | * #address-cells: should be 1. | ||
| 13 | * #size-cells: should be 0. | ||
| 14 | |||
| 15 | # Slots: The slot specific information are contained within child-nodes with | ||
| 16 | each child-node representing a supported slot. There should be atleast one | ||
| 17 | child node representing a card slot. The name of the child node representing | ||
| 18 | the slot is recommended to be slot@n where n is the unique number of the slot | ||
| 19 | connnected to the controller. The following are optional properties which | ||
| 20 | can be included in the slot child node. | ||
| 21 | |||
| 22 | * reg: specifies the physical slot number. The valid values of this | ||
| 23 | property is 0 to (num-slots -1), where num-slots is the value | ||
| 24 | specified by the num-slots property. | ||
| 25 | |||
| 26 | * bus-width: as documented in mmc core bindings. | ||
| 27 | |||
| 28 | * wp-gpios: specifies the write protect gpio line. The format of the | ||
| 29 | gpio specifier depends on the gpio controller. If the write-protect | ||
| 30 | line is not available, this property is optional. | ||
| 31 | |||
| 32 | Optional properties: | ||
| 33 | |||
| 34 | * num-slots: specifies the number of slots supported by the controller. | ||
| 35 | The number of physical slots actually used could be equal or less than the | ||
| 36 | value specified by num-slots. If this property is not specified, the value | ||
| 37 | of num-slot property is assumed to be 1. | ||
| 38 | |||
| 39 | * fifo-depth: The maximum size of the tx/rx fifo's. If this property is not | ||
| 40 | specified, the default value of the fifo size is determined from the | ||
| 41 | controller registers. | ||
| 42 | |||
| 43 | * card-detect-delay: Delay in milli-seconds before detecting card after card | ||
| 44 | insert event. The default value is 0. | ||
| 45 | |||
| 46 | * supports-highspeed: Enables support for high speed cards (upto 50MHz) | ||
| 47 | |||
| 48 | * broken-cd: as documented in mmc core bindings. | ||
| 49 | |||
| 50 | Aliases: | ||
| 51 | |||
| 52 | - All the MSHC controller nodes should be represented in the aliases node using | ||
| 53 | the following format 'mshc{n}' where n is a unique number for the alias. | ||
| 54 | |||
| 55 | Example: | ||
| 56 | |||
| 57 | The MSHC controller node can be split into two portions, SoC specific and | ||
| 58 | board specific portions as listed below. | ||
| 59 | |||
| 60 | dwmmc0@12200000 { | ||
| 61 | compatible = "snps,dw-mshc"; | ||
| 62 | reg = <0x12200000 0x1000>; | ||
| 63 | interrupts = <0 75 0>; | ||
| 64 | #address-cells = <1>; | ||
| 65 | #size-cells = <0>; | ||
| 66 | }; | ||
| 67 | |||
| 68 | dwmmc0@12200000 { | ||
| 69 | num-slots = <1>; | ||
| 70 | supports-highspeed; | ||
| 71 | broken-cd; | ||
| 72 | fifo-depth = <0x80>; | ||
| 73 | card-detect-delay = <200>; | ||
| 74 | |||
| 75 | slot@0 { | ||
| 76 | reg = <0>; | ||
| 77 | bus-width = <8>; | ||
| 78 | }; | ||
| 79 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index eae3cd86831e..0f6ff811da07 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -1544,7 +1544,7 @@ S: Supported | |||
| 1544 | F: drivers/rtc/rtc-bfin.c | 1544 | F: drivers/rtc/rtc-bfin.c |
| 1545 | 1545 | ||
| 1546 | BLACKFIN SDH DRIVER | 1546 | BLACKFIN SDH DRIVER |
| 1547 | M: Cliff Cai <cliff.cai@analog.com> | 1547 | M: Sonic Zhang <sonic.zhang@analog.com> |
| 1548 | L: uclinux-dist-devel@blackfin.uclinux.org | 1548 | L: uclinux-dist-devel@blackfin.uclinux.org |
| 1549 | W: http://blackfin.uclinux.org | 1549 | W: http://blackfin.uclinux.org |
| 1550 | S: Supported | 1550 | S: Supported |
| @@ -5207,8 +5207,10 @@ S: Maintained | |||
| 5207 | F: drivers/mmc/host/omap.c | 5207 | F: drivers/mmc/host/omap.c |
| 5208 | 5208 | ||
| 5209 | OMAP HS MMC SUPPORT | 5209 | OMAP HS MMC SUPPORT |
| 5210 | M: Venkatraman S <svenkatr@ti.com> | ||
| 5211 | L: linux-mmc@vger.kernel.org | ||
| 5210 | L: linux-omap@vger.kernel.org | 5212 | L: linux-omap@vger.kernel.org |
| 5211 | S: Orphan | 5213 | S: Maintained |
| 5212 | F: drivers/mmc/host/omap_hsmmc.c | 5214 | F: drivers/mmc/host/omap_hsmmc.c |
| 5213 | 5215 | ||
| 5214 | OMAP RANDOM NUMBER GENERATOR SUPPORT | 5216 | OMAP RANDOM NUMBER GENERATOR SUPPORT |
diff --git a/arch/arm/boot/dts/spear300-evb.dts b/arch/arm/boot/dts/spear300-evb.dts index d71b8d581e3d..1e7c7a8e2123 100644 --- a/arch/arm/boot/dts/spear300-evb.dts +++ b/arch/arm/boot/dts/spear300-evb.dts | |||
| @@ -80,8 +80,7 @@ | |||
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | sdhci@70000000 { | 82 | sdhci@70000000 { |
| 83 | int-gpio = <&gpio1 0 0>; | 83 | cd-gpios = <&gpio1 0 0>; |
| 84 | power-gpio = <&gpio1 2 1>; | ||
| 85 | status = "okay"; | 84 | status = "okay"; |
| 86 | }; | 85 | }; |
| 87 | 86 | ||
diff --git a/arch/arm/boot/dts/spear320-evb.dts b/arch/arm/boot/dts/spear320-evb.dts index e4e912f95024..082328bd64ab 100644 --- a/arch/arm/boot/dts/spear320-evb.dts +++ b/arch/arm/boot/dts/spear320-evb.dts | |||
| @@ -103,8 +103,6 @@ | |||
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | sdhci@70000000 { | 105 | sdhci@70000000 { |
| 106 | power-gpio = <&gpio0 2 1>; | ||
| 107 | power_always_enb; | ||
| 108 | status = "okay"; | 106 | status = "okay"; |
| 109 | }; | 107 | }; |
| 110 | 108 | ||
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 8ac5246e2ab2..06c42cfb7c34 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/suspend.h> | 26 | #include <linux/suspend.h> |
| 27 | #include <linux/fault-inject.h> | 27 | #include <linux/fault-inject.h> |
| 28 | #include <linux/random.h> | 28 | #include <linux/random.h> |
| 29 | #include <linux/slab.h> | ||
| 29 | 30 | ||
| 30 | #include <linux/mmc/card.h> | 31 | #include <linux/mmc/card.h> |
| 31 | #include <linux/mmc/host.h> | 32 | #include <linux/mmc/host.h> |
| @@ -41,6 +42,12 @@ | |||
| 41 | #include "sd_ops.h" | 42 | #include "sd_ops.h" |
| 42 | #include "sdio_ops.h" | 43 | #include "sdio_ops.h" |
| 43 | 44 | ||
| 45 | /* | ||
| 46 | * Background operations can take a long time, depending on the housekeeping | ||
| 47 | * operations the card has to perform. | ||
| 48 | */ | ||
| 49 | #define MMC_BKOPS_MAX_TIMEOUT (4 * 60 * 1000) /* max time to wait in ms */ | ||
| 50 | |||
| 44 | static struct workqueue_struct *workqueue; | 51 | static struct workqueue_struct *workqueue; |
| 45 | static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; | 52 | static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; |
| 46 | 53 | ||
| @@ -245,6 +252,70 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) | |||
| 245 | host->ops->request(host, mrq); | 252 | host->ops->request(host, mrq); |
| 246 | } | 253 | } |
| 247 | 254 | ||
| 255 | /** | ||
| 256 | * mmc_start_bkops - start BKOPS for supported cards | ||
| 257 | * @card: MMC card to start BKOPS | ||
| 258 | * @form_exception: A flag to indicate if this function was | ||
| 259 | * called due to an exception raised by the card | ||
| 260 | * | ||
| 261 | * Start background operations whenever requested. | ||
| 262 | * When the urgent BKOPS bit is set in a R1 command response | ||
| 263 | * then background operations should be started immediately. | ||
| 264 | */ | ||
| 265 | void mmc_start_bkops(struct mmc_card *card, bool from_exception) | ||
| 266 | { | ||
| 267 | int err; | ||
| 268 | int timeout; | ||
| 269 | bool use_busy_signal; | ||
| 270 | |||
| 271 | BUG_ON(!card); | ||
| 272 | |||
| 273 | if (!card->ext_csd.bkops_en || mmc_card_doing_bkops(card)) | ||
| 274 | return; | ||
| 275 | |||
| 276 | err = mmc_read_bkops_status(card); | ||
| 277 | if (err) { | ||
| 278 | pr_err("%s: Failed to read bkops status: %d\n", | ||
| 279 | mmc_hostname(card->host), err); | ||
| 280 | return; | ||
| 281 | } | ||
| 282 | |||
| 283 | if (!card->ext_csd.raw_bkops_status) | ||
| 284 | return; | ||
| 285 | |||
| 286 | if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 && | ||
| 287 | from_exception) | ||
| 288 | return; | ||
| 289 | |||
| 290 | mmc_claim_host(card->host); | ||
| 291 | if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) { | ||
| 292 | timeout = MMC_BKOPS_MAX_TIMEOUT; | ||
| 293 | use_busy_signal = true; | ||
| 294 | } else { | ||
| 295 | timeout = 0; | ||
| 296 | use_busy_signal = false; | ||
| 297 | } | ||
| 298 | |||
| 299 | err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
| 300 | EXT_CSD_BKOPS_START, 1, timeout, use_busy_signal); | ||
| 301 | if (err) { | ||
| 302 | pr_warn("%s: Error %d starting bkops\n", | ||
| 303 | mmc_hostname(card->host), err); | ||
| 304 | goto out; | ||
| 305 | } | ||
| 306 | |||
| 307 | /* | ||
| 308 | * For urgent bkops status (LEVEL_2 and more) | ||
| 309 | * bkops executed synchronously, otherwise | ||
| 310 | * the operation is in progress | ||
| 311 | */ | ||
| 312 | if (!use_busy_signal) | ||
| 313 | mmc_card_set_doing_bkops(card); | ||
| 314 | out: | ||
| 315 | mmc_release_host(card->host); | ||
| 316 | } | ||
| 317 | EXPORT_SYMBOL(mmc_start_bkops); | ||
| 318 | |||
| 248 | static void mmc_wait_done(struct mmc_request *mrq) | 319 | static void mmc_wait_done(struct mmc_request *mrq) |
| 249 | { | 320 | { |
| 250 | complete(&mrq->completion); | 321 | complete(&mrq->completion); |
| @@ -354,6 +425,14 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host, | |||
| 354 | if (host->areq) { | 425 | if (host->areq) { |
| 355 | mmc_wait_for_req_done(host, host->areq->mrq); | 426 | mmc_wait_for_req_done(host, host->areq->mrq); |
| 356 | err = host->areq->err_check(host->card, host->areq); | 427 | err = host->areq->err_check(host->card, host->areq); |
| 428 | /* | ||
| 429 | * Check BKOPS urgency for each R1 response | ||
| 430 | */ | ||
| 431 | if (host->card && mmc_card_mmc(host->card) && | ||
| 432 | ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) || | ||
| 433 | (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) && | ||
| 434 | (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT)) | ||
| 435 | mmc_start_bkops(host->card, true); | ||
| 357 | } | 436 | } |
| 358 | 437 | ||
| 359 | if (!err && areq) | 438 | if (!err && areq) |
| @@ -398,7 +477,7 @@ EXPORT_SYMBOL(mmc_wait_for_req); | |||
| 398 | * @card: the MMC card associated with the HPI transfer | 477 | * @card: the MMC card associated with the HPI transfer |
| 399 | * | 478 | * |
| 400 | * Issued High Priority Interrupt, and check for card status | 479 | * Issued High Priority Interrupt, and check for card status |
| 401 | * util out-of prg-state. | 480 | * until out-of prg-state. |
| 402 | */ | 481 | */ |
| 403 | int mmc_interrupt_hpi(struct mmc_card *card) | 482 | int mmc_interrupt_hpi(struct mmc_card *card) |
| 404 | { | 483 | { |
| @@ -424,8 +503,9 @@ int mmc_interrupt_hpi(struct mmc_card *card) | |||
| 424 | case R1_STATE_IDLE: | 503 | case R1_STATE_IDLE: |
| 425 | case R1_STATE_READY: | 504 | case R1_STATE_READY: |
| 426 | case R1_STATE_STBY: | 505 | case R1_STATE_STBY: |
| 506 | case R1_STATE_TRAN: | ||
| 427 | /* | 507 | /* |
| 428 | * In idle states, HPI is not needed and the caller | 508 | * In idle and transfer states, HPI is not needed and the caller |
| 429 | * can issue the next intended command immediately | 509 | * can issue the next intended command immediately |
| 430 | */ | 510 | */ |
| 431 | goto out; | 511 | goto out; |
| @@ -489,6 +569,64 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries | |||
| 489 | EXPORT_SYMBOL(mmc_wait_for_cmd); | 569 | EXPORT_SYMBOL(mmc_wait_for_cmd); |
| 490 | 570 | ||
| 491 | /** | 571 | /** |
| 572 | * mmc_stop_bkops - stop ongoing BKOPS | ||
| 573 | * @card: MMC card to check BKOPS | ||
| 574 | * | ||
| 575 | * Send HPI command to stop ongoing background operations to | ||
| 576 | * allow rapid servicing of foreground operations, e.g. read/ | ||
| 577 | * writes. Wait until the card comes out of the programming state | ||
| 578 | * to avoid errors in servicing read/write requests. | ||
| 579 | */ | ||
| 580 | int mmc_stop_bkops(struct mmc_card *card) | ||
| 581 | { | ||
| 582 | int err = 0; | ||
| 583 | |||
| 584 | BUG_ON(!card); | ||
| 585 | err = mmc_interrupt_hpi(card); | ||
| 586 | |||
| 587 | /* | ||
| 588 | * If err is EINVAL, we can't issue an HPI. | ||
| 589 | * It should complete the BKOPS. | ||
| 590 | */ | ||
| 591 | if (!err || (err == -EINVAL)) { | ||
| 592 | mmc_card_clr_doing_bkops(card); | ||
| 593 | err = 0; | ||
| 594 | } | ||
| 595 | |||
| 596 | return err; | ||
| 597 | } | ||
| 598 | EXPORT_SYMBOL(mmc_stop_bkops); | ||
| 599 | |||
| 600 | int mmc_read_bkops_status(struct mmc_card *card) | ||
| 601 | { | ||
| 602 | int err; | ||
| 603 | u8 *ext_csd; | ||
| 604 | |||
| 605 | /* | ||
| 606 | * In future work, we should consider storing the entire ext_csd. | ||
| 607 | */ | ||
| 608 | ext_csd = kmalloc(512, GFP_KERNEL); | ||
| 609 | if (!ext_csd) { | ||
| 610 | pr_err("%s: could not allocate buffer to receive the ext_csd.\n", | ||
| 611 | mmc_hostname(card->host)); | ||
| 612 | return -ENOMEM; | ||
| 613 | } | ||
| 614 | |||
| 615 | mmc_claim_host(card->host); | ||
| 616 | err = mmc_send_ext_csd(card, ext_csd); | ||
| 617 | mmc_release_host(card->host); | ||
| 618 | if (err) | ||
| 619 | goto out; | ||
| 620 | |||
| 621 | card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS]; | ||
| 622 | card->ext_csd.raw_exception_status = ext_csd[EXT_CSD_EXP_EVENTS_STATUS]; | ||
| 623 | out: | ||
| 624 | kfree(ext_csd); | ||
| 625 | return err; | ||
| 626 | } | ||
| 627 | EXPORT_SYMBOL(mmc_read_bkops_status); | ||
| 628 | |||
| 629 | /** | ||
| 492 | * mmc_set_data_timeout - set the timeout for a data command | 630 | * mmc_set_data_timeout - set the timeout for a data command |
| 493 | * @data: data phase for command | 631 | * @data: data phase for command |
| 494 | * @card: the MMC card associated with the data transfer | 632 | * @card: the MMC card associated with the data transfer |
| @@ -975,7 +1113,8 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, | |||
| 975 | int tmp; | 1113 | int tmp; |
| 976 | int voltage; | 1114 | int voltage; |
| 977 | 1115 | ||
| 978 | /* REVISIT mmc_vddrange_to_ocrmask() may have set some | 1116 | /* |
| 1117 | * REVISIT mmc_vddrange_to_ocrmask() may have set some | ||
| 979 | * bits this regulator doesn't quite support ... don't | 1118 | * bits this regulator doesn't quite support ... don't |
| 980 | * be too picky, most cards and regulators are OK with | 1119 | * be too picky, most cards and regulators are OK with |
| 981 | * a 0.1V range goof (it's a small error percentage). | 1120 | * a 0.1V range goof (it's a small error percentage). |
| @@ -989,12 +1128,13 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, | |||
| 989 | max_uV = min_uV + 100 * 1000; | 1128 | max_uV = min_uV + 100 * 1000; |
| 990 | } | 1129 | } |
| 991 | 1130 | ||
| 992 | /* avoid needless changes to this voltage; the regulator | 1131 | /* |
| 993 | * might not allow this operation | 1132 | * If we're using a fixed/static regulator, don't call |
| 1133 | * regulator_set_voltage; it would fail. | ||
| 994 | */ | 1134 | */ |
| 995 | voltage = regulator_get_voltage(supply); | 1135 | voltage = regulator_get_voltage(supply); |
| 996 | 1136 | ||
| 997 | if (mmc->caps2 & MMC_CAP2_BROKEN_VOLTAGE) | 1137 | if (regulator_count_voltages(supply) == 1) |
| 998 | min_uV = max_uV = voltage; | 1138 | min_uV = max_uV = voltage; |
| 999 | 1139 | ||
| 1000 | if (voltage < 0) | 1140 | if (voltage < 0) |
| @@ -1133,48 +1273,6 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type) | |||
| 1133 | mmc_host_clk_release(host); | 1273 | mmc_host_clk_release(host); |
| 1134 | } | 1274 | } |
| 1135 | 1275 | ||
| 1136 | static void mmc_poweroff_notify(struct mmc_host *host) | ||
| 1137 | { | ||
| 1138 | struct mmc_card *card; | ||
| 1139 | unsigned int timeout; | ||
| 1140 | unsigned int notify_type = EXT_CSD_NO_POWER_NOTIFICATION; | ||
| 1141 | int err = 0; | ||
| 1142 | |||
| 1143 | card = host->card; | ||
| 1144 | mmc_claim_host(host); | ||
| 1145 | |||
| 1146 | /* | ||
| 1147 | * Send power notify command only if card | ||
| 1148 | * is mmc and notify state is powered ON | ||
| 1149 | */ | ||
| 1150 | if (card && mmc_card_mmc(card) && | ||
| 1151 | (card->poweroff_notify_state == MMC_POWERED_ON)) { | ||
| 1152 | |||
| 1153 | if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) { | ||
| 1154 | notify_type = EXT_CSD_POWER_OFF_SHORT; | ||
| 1155 | timeout = card->ext_csd.generic_cmd6_time; | ||
| 1156 | card->poweroff_notify_state = MMC_POWEROFF_SHORT; | ||
| 1157 | } else { | ||
| 1158 | notify_type = EXT_CSD_POWER_OFF_LONG; | ||
| 1159 | timeout = card->ext_csd.power_off_longtime; | ||
| 1160 | card->poweroff_notify_state = MMC_POWEROFF_LONG; | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
| 1164 | EXT_CSD_POWER_OFF_NOTIFICATION, | ||
| 1165 | notify_type, timeout); | ||
| 1166 | |||
| 1167 | if (err && err != -EBADMSG) | ||
| 1168 | pr_err("Device failed to respond within %d poweroff " | ||
| 1169 | "time. Forcefully powering down the device\n", | ||
| 1170 | timeout); | ||
| 1171 | |||
| 1172 | /* Set the card state to no notification after the poweroff */ | ||
| 1173 | card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION; | ||
| 1174 | } | ||
| 1175 | mmc_release_host(host); | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | /* | 1276 | /* |
| 1179 | * Apply power to the MMC stack. This is a two-stage process. | 1277 | * Apply power to the MMC stack. This is a two-stage process. |
| 1180 | * First, we enable power to the card without the clock running. | 1278 | * First, we enable power to the card without the clock running. |
| @@ -1237,8 +1335,6 @@ static void mmc_power_up(struct mmc_host *host) | |||
| 1237 | 1335 | ||
| 1238 | void mmc_power_off(struct mmc_host *host) | 1336 | void mmc_power_off(struct mmc_host *host) |
| 1239 | { | 1337 | { |
| 1240 | int err = 0; | ||
| 1241 | |||
| 1242 | if (host->ios.power_mode == MMC_POWER_OFF) | 1338 | if (host->ios.power_mode == MMC_POWER_OFF) |
| 1243 | return; | 1339 | return; |
| 1244 | 1340 | ||
| @@ -1247,22 +1343,6 @@ void mmc_power_off(struct mmc_host *host) | |||
| 1247 | host->ios.clock = 0; | 1343 | host->ios.clock = 0; |
| 1248 | host->ios.vdd = 0; | 1344 | host->ios.vdd = 0; |
| 1249 | 1345 | ||
| 1250 | /* | ||
| 1251 | * For eMMC 4.5 device send AWAKE command before | ||
| 1252 | * POWER_OFF_NOTIFY command, because in sleep state | ||
| 1253 | * eMMC 4.5 devices respond to only RESET and AWAKE cmd | ||
| 1254 | */ | ||
| 1255 | if (host->card && mmc_card_is_sleep(host->card) && | ||
| 1256 | host->bus_ops->resume) { | ||
| 1257 | err = host->bus_ops->resume(host); | ||
| 1258 | |||
| 1259 | if (!err) | ||
| 1260 | mmc_poweroff_notify(host); | ||
| 1261 | else | ||
| 1262 | pr_warning("%s: error %d during resume " | ||
| 1263 | "(continue with poweroff sequence)\n", | ||
| 1264 | mmc_hostname(host), err); | ||
| 1265 | } | ||
| 1266 | 1346 | ||
| 1267 | /* | 1347 | /* |
| 1268 | * Reset ocr mask to be the highest possible voltage supported for | 1348 | * Reset ocr mask to be the highest possible voltage supported for |
| @@ -2052,6 +2132,11 @@ void mmc_rescan(struct work_struct *work) | |||
| 2052 | if (host->rescan_disable) | 2132 | if (host->rescan_disable) |
| 2053 | return; | 2133 | return; |
| 2054 | 2134 | ||
| 2135 | /* If there is a non-removable card registered, only scan once */ | ||
| 2136 | if ((host->caps & MMC_CAP_NONREMOVABLE) && host->rescan_entered) | ||
| 2137 | return; | ||
| 2138 | host->rescan_entered = 1; | ||
| 2139 | |||
| 2055 | mmc_bus_get(host); | 2140 | mmc_bus_get(host); |
| 2056 | 2141 | ||
| 2057 | /* | 2142 | /* |
| @@ -2327,9 +2412,14 @@ int mmc_suspend_host(struct mmc_host *host) | |||
| 2327 | 2412 | ||
| 2328 | mmc_bus_get(host); | 2413 | mmc_bus_get(host); |
| 2329 | if (host->bus_ops && !host->bus_dead) { | 2414 | if (host->bus_ops && !host->bus_dead) { |
| 2330 | 2415 | if (host->bus_ops->suspend) { | |
| 2331 | if (host->bus_ops->suspend) | 2416 | if (mmc_card_doing_bkops(host->card)) { |
| 2417 | err = mmc_stop_bkops(host->card); | ||
| 2418 | if (err) | ||
| 2419 | goto out; | ||
| 2420 | } | ||
| 2332 | err = host->bus_ops->suspend(host); | 2421 | err = host->bus_ops->suspend(host); |
| 2422 | } | ||
| 2333 | 2423 | ||
| 2334 | if (err == -ENOSYS || !host->bus_ops->resume) { | 2424 | if (err == -ENOSYS || !host->bus_ops->resume) { |
| 2335 | /* | 2425 | /* |
| @@ -2411,15 +2501,24 @@ int mmc_pm_notify(struct notifier_block *notify_block, | |||
| 2411 | struct mmc_host *host = container_of( | 2501 | struct mmc_host *host = container_of( |
| 2412 | notify_block, struct mmc_host, pm_notify); | 2502 | notify_block, struct mmc_host, pm_notify); |
| 2413 | unsigned long flags; | 2503 | unsigned long flags; |
| 2414 | 2504 | int err = 0; | |
| 2415 | 2505 | ||
| 2416 | switch (mode) { | 2506 | switch (mode) { |
| 2417 | case PM_HIBERNATION_PREPARE: | 2507 | case PM_HIBERNATION_PREPARE: |
| 2418 | case PM_SUSPEND_PREPARE: | 2508 | case PM_SUSPEND_PREPARE: |
| 2509 | if (host->card && mmc_card_mmc(host->card) && | ||
| 2510 | mmc_card_doing_bkops(host->card)) { | ||
| 2511 | err = mmc_stop_bkops(host->card); | ||
| 2512 | if (err) { | ||
| 2513 | pr_err("%s: didn't stop bkops\n", | ||
| 2514 | mmc_hostname(host)); | ||
| 2515 | return err; | ||
| 2516 | } | ||
| 2517 | mmc_card_clr_doing_bkops(host->card); | ||
| 2518 | } | ||
| 2419 | 2519 | ||
| 2420 | spin_lock_irqsave(&host->lock, flags); | 2520 | spin_lock_irqsave(&host->lock, flags); |
| 2421 | host->rescan_disable = 1; | 2521 | host->rescan_disable = 1; |
| 2422 | host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT; | ||
| 2423 | spin_unlock_irqrestore(&host->lock, flags); | 2522 | spin_unlock_irqrestore(&host->lock, flags); |
| 2424 | cancel_delayed_work_sync(&host->detect); | 2523 | cancel_delayed_work_sync(&host->detect); |
| 2425 | 2524 | ||
| @@ -2443,7 +2542,6 @@ int mmc_pm_notify(struct notifier_block *notify_block, | |||
| 2443 | 2542 | ||
| 2444 | spin_lock_irqsave(&host->lock, flags); | 2543 | spin_lock_irqsave(&host->lock, flags); |
| 2445 | host->rescan_disable = 0; | 2544 | host->rescan_disable = 0; |
| 2446 | host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG; | ||
| 2447 | spin_unlock_irqrestore(&host->lock, flags); | 2545 | spin_unlock_irqrestore(&host->lock, flags); |
| 2448 | mmc_detect_change(host, 0); | 2546 | mmc_detect_change(host, 0); |
| 2449 | 2547 | ||
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 9ab5b17d488a..d96c643dde1c 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c | |||
| @@ -281,7 +281,7 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp) | |||
| 281 | if (err) | 281 | if (err) |
| 282 | goto out_free; | 282 | goto out_free; |
| 283 | 283 | ||
| 284 | for (i = 511; i >= 0; i--) | 284 | for (i = 0; i < 512; i++) |
| 285 | n += sprintf(buf + n, "%02x", ext_csd[i]); | 285 | n += sprintf(buf + n, "%02x", ext_csd[i]); |
| 286 | n += sprintf(buf + n, "\n"); | 286 | n += sprintf(buf + n, "\n"); |
| 287 | BUG_ON(n != EXT_CSD_STR_LEN); | 287 | BUG_ON(n != EXT_CSD_STR_LEN); |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 396b25891bb9..7cc46382fd64 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
| @@ -463,6 +463,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | if (card->ext_csd.rev >= 5) { | 465 | if (card->ext_csd.rev >= 5) { |
| 466 | /* check whether the eMMC card supports BKOPS */ | ||
| 467 | if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { | ||
| 468 | card->ext_csd.bkops = 1; | ||
| 469 | card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN]; | ||
| 470 | card->ext_csd.raw_bkops_status = | ||
| 471 | ext_csd[EXT_CSD_BKOPS_STATUS]; | ||
| 472 | if (!card->ext_csd.bkops_en) | ||
| 473 | pr_info("%s: BKOPS_EN bit is not set\n", | ||
| 474 | mmc_hostname(card->host)); | ||
| 475 | } | ||
| 476 | |||
| 466 | /* check whether the eMMC card supports HPI */ | 477 | /* check whether the eMMC card supports HPI */ |
| 467 | if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) { | 478 | if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) { |
| 468 | card->ext_csd.hpi = 1; | 479 | card->ext_csd.hpi = 1; |
| @@ -996,7 +1007,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 996 | * so check for success and update the flag | 1007 | * so check for success and update the flag |
| 997 | */ | 1008 | */ |
| 998 | if (!err) | 1009 | if (!err) |
| 999 | card->poweroff_notify_state = MMC_POWERED_ON; | 1010 | card->ext_csd.power_off_notification = EXT_CSD_POWER_ON; |
| 1000 | } | 1011 | } |
| 1001 | 1012 | ||
| 1002 | /* | 1013 | /* |
| @@ -1262,6 +1273,35 @@ err: | |||
| 1262 | return err; | 1273 | return err; |
| 1263 | } | 1274 | } |
| 1264 | 1275 | ||
| 1276 | static int mmc_can_poweroff_notify(const struct mmc_card *card) | ||
| 1277 | { | ||
| 1278 | return card && | ||
| 1279 | mmc_card_mmc(card) && | ||
| 1280 | (card->ext_csd.power_off_notification == EXT_CSD_POWER_ON); | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) | ||
| 1284 | { | ||
| 1285 | unsigned int timeout = card->ext_csd.generic_cmd6_time; | ||
| 1286 | int err; | ||
| 1287 | |||
| 1288 | /* Use EXT_CSD_POWER_OFF_SHORT as default notification type. */ | ||
| 1289 | if (notify_type == EXT_CSD_POWER_OFF_LONG) | ||
| 1290 | timeout = card->ext_csd.power_off_longtime; | ||
| 1291 | |||
| 1292 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
| 1293 | EXT_CSD_POWER_OFF_NOTIFICATION, | ||
| 1294 | notify_type, timeout); | ||
| 1295 | if (err) | ||
| 1296 | pr_err("%s: Power Off Notification timed out, %u\n", | ||
| 1297 | mmc_hostname(card->host), timeout); | ||
| 1298 | |||
| 1299 | /* Disable the power off notification after the switch operation. */ | ||
| 1300 | card->ext_csd.power_off_notification = EXT_CSD_NO_POWER_NOTIFICATION; | ||
| 1301 | |||
| 1302 | return err; | ||
| 1303 | } | ||
| 1304 | |||
| 1265 | /* | 1305 | /* |
| 1266 | * Host is being removed. Free up the current card. | 1306 | * Host is being removed. Free up the current card. |
| 1267 | */ | 1307 | */ |
| @@ -1322,11 +1362,11 @@ static int mmc_suspend(struct mmc_host *host) | |||
| 1322 | BUG_ON(!host->card); | 1362 | BUG_ON(!host->card); |
| 1323 | 1363 | ||
| 1324 | mmc_claim_host(host); | 1364 | mmc_claim_host(host); |
| 1325 | if (mmc_card_can_sleep(host)) { | 1365 | if (mmc_can_poweroff_notify(host->card)) |
| 1366 | err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT); | ||
| 1367 | else if (mmc_card_can_sleep(host)) | ||
| 1326 | err = mmc_card_sleep(host); | 1368 | err = mmc_card_sleep(host); |
| 1327 | if (!err) | 1369 | else if (!mmc_host_is_spi(host)) |
| 1328 | mmc_card_set_sleep(host->card); | ||
| 1329 | } else if (!mmc_host_is_spi(host)) | ||
| 1330 | err = mmc_deselect_cards(host); | 1370 | err = mmc_deselect_cards(host); |
| 1331 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); | 1371 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); |
| 1332 | mmc_release_host(host); | 1372 | mmc_release_host(host); |
| @@ -1348,11 +1388,7 @@ static int mmc_resume(struct mmc_host *host) | |||
| 1348 | BUG_ON(!host->card); | 1388 | BUG_ON(!host->card); |
| 1349 | 1389 | ||
| 1350 | mmc_claim_host(host); | 1390 | mmc_claim_host(host); |
| 1351 | if (mmc_card_is_sleep(host->card)) { | 1391 | err = mmc_init_card(host, host->ocr, host->card); |
| 1352 | err = mmc_card_awake(host); | ||
| 1353 | mmc_card_clr_sleep(host->card); | ||
| 1354 | } else | ||
| 1355 | err = mmc_init_card(host, host->ocr, host->card); | ||
| 1356 | mmc_release_host(host); | 1392 | mmc_release_host(host); |
| 1357 | 1393 | ||
| 1358 | return err; | 1394 | return err; |
| @@ -1363,7 +1399,6 @@ static int mmc_power_restore(struct mmc_host *host) | |||
| 1363 | int ret; | 1399 | int ret; |
| 1364 | 1400 | ||
| 1365 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); | 1401 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); |
| 1366 | mmc_card_clr_sleep(host->card); | ||
| 1367 | mmc_claim_host(host); | 1402 | mmc_claim_host(host); |
| 1368 | ret = mmc_init_card(host, host->ocr, host->card); | 1403 | ret = mmc_init_card(host, host->ocr, host->card); |
| 1369 | mmc_release_host(host); | 1404 | mmc_release_host(host); |
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 0ed2cc5f35b6..a0e172042e65 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c | |||
| @@ -230,6 +230,10 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) | |||
| 230 | return 0; | 230 | return 0; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | /* | ||
| 234 | * NOTE: void *buf, caller for the buf is required to use DMA-capable | ||
| 235 | * buffer or on-stack buffer (with some overhead in callee). | ||
| 236 | */ | ||
| 233 | static int | 237 | static int |
| 234 | mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, | 238 | mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, |
| 235 | u32 opcode, void *buf, unsigned len) | 239 | u32 opcode, void *buf, unsigned len) |
| @@ -239,13 +243,19 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, | |||
| 239 | struct mmc_data data = {0}; | 243 | struct mmc_data data = {0}; |
| 240 | struct scatterlist sg; | 244 | struct scatterlist sg; |
| 241 | void *data_buf; | 245 | void *data_buf; |
| 246 | int is_on_stack; | ||
| 242 | 247 | ||
| 243 | /* dma onto stack is unsafe/nonportable, but callers to this | 248 | is_on_stack = object_is_on_stack(buf); |
| 244 | * routine normally provide temporary on-stack buffers ... | 249 | if (is_on_stack) { |
| 245 | */ | 250 | /* |
| 246 | data_buf = kmalloc(len, GFP_KERNEL); | 251 | * dma onto stack is unsafe/nonportable, but callers to this |
| 247 | if (data_buf == NULL) | 252 | * routine normally provide temporary on-stack buffers ... |
| 248 | return -ENOMEM; | 253 | */ |
| 254 | data_buf = kmalloc(len, GFP_KERNEL); | ||
| 255 | if (!data_buf) | ||
| 256 | return -ENOMEM; | ||
| 257 | } else | ||
| 258 | data_buf = buf; | ||
| 249 | 259 | ||
| 250 | mrq.cmd = &cmd; | 260 | mrq.cmd = &cmd; |
| 251 | mrq.data = &data; | 261 | mrq.data = &data; |
| @@ -280,8 +290,10 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, | |||
| 280 | 290 | ||
| 281 | mmc_wait_for_req(host, &mrq); | 291 | mmc_wait_for_req(host, &mrq); |
| 282 | 292 | ||
| 283 | memcpy(buf, data_buf, len); | 293 | if (is_on_stack) { |
| 284 | kfree(data_buf); | 294 | memcpy(buf, data_buf, len); |
| 295 | kfree(data_buf); | ||
| 296 | } | ||
| 285 | 297 | ||
| 286 | if (cmd.error) | 298 | if (cmd.error) |
| 287 | return cmd.error; | 299 | return cmd.error; |
| @@ -294,24 +306,32 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, | |||
| 294 | int mmc_send_csd(struct mmc_card *card, u32 *csd) | 306 | int mmc_send_csd(struct mmc_card *card, u32 *csd) |
| 295 | { | 307 | { |
| 296 | int ret, i; | 308 | int ret, i; |
| 309 | u32 *csd_tmp; | ||
| 297 | 310 | ||
| 298 | if (!mmc_host_is_spi(card->host)) | 311 | if (!mmc_host_is_spi(card->host)) |
| 299 | return mmc_send_cxd_native(card->host, card->rca << 16, | 312 | return mmc_send_cxd_native(card->host, card->rca << 16, |
| 300 | csd, MMC_SEND_CSD); | 313 | csd, MMC_SEND_CSD); |
| 301 | 314 | ||
| 302 | ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd, 16); | 315 | csd_tmp = kmalloc(16, GFP_KERNEL); |
| 316 | if (!csd_tmp) | ||
| 317 | return -ENOMEM; | ||
| 318 | |||
| 319 | ret = mmc_send_cxd_data(card, card->host, MMC_SEND_CSD, csd_tmp, 16); | ||
| 303 | if (ret) | 320 | if (ret) |
| 304 | return ret; | 321 | goto err; |
| 305 | 322 | ||
| 306 | for (i = 0;i < 4;i++) | 323 | for (i = 0;i < 4;i++) |
| 307 | csd[i] = be32_to_cpu(csd[i]); | 324 | csd[i] = be32_to_cpu(csd_tmp[i]); |
| 308 | 325 | ||
| 309 | return 0; | 326 | err: |
| 327 | kfree(csd_tmp); | ||
| 328 | return ret; | ||
| 310 | } | 329 | } |
| 311 | 330 | ||
| 312 | int mmc_send_cid(struct mmc_host *host, u32 *cid) | 331 | int mmc_send_cid(struct mmc_host *host, u32 *cid) |
| 313 | { | 332 | { |
| 314 | int ret, i; | 333 | int ret, i; |
| 334 | u32 *cid_tmp; | ||
| 315 | 335 | ||
| 316 | if (!mmc_host_is_spi(host)) { | 336 | if (!mmc_host_is_spi(host)) { |
| 317 | if (!host->card) | 337 | if (!host->card) |
| @@ -320,14 +340,20 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid) | |||
| 320 | cid, MMC_SEND_CID); | 340 | cid, MMC_SEND_CID); |
| 321 | } | 341 | } |
| 322 | 342 | ||
| 323 | ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid, 16); | 343 | cid_tmp = kmalloc(16, GFP_KERNEL); |
| 344 | if (!cid_tmp) | ||
| 345 | return -ENOMEM; | ||
| 346 | |||
| 347 | ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid_tmp, 16); | ||
| 324 | if (ret) | 348 | if (ret) |
| 325 | return ret; | 349 | goto err; |
| 326 | 350 | ||
| 327 | for (i = 0;i < 4;i++) | 351 | for (i = 0;i < 4;i++) |
| 328 | cid[i] = be32_to_cpu(cid[i]); | 352 | cid[i] = be32_to_cpu(cid_tmp[i]); |
| 329 | 353 | ||
| 330 | return 0; | 354 | err: |
| 355 | kfree(cid_tmp); | ||
| 356 | return ret; | ||
| 331 | } | 357 | } |
| 332 | 358 | ||
| 333 | int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) | 359 | int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd) |
| @@ -367,18 +393,19 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc) | |||
| 367 | } | 393 | } |
| 368 | 394 | ||
| 369 | /** | 395 | /** |
| 370 | * mmc_switch - modify EXT_CSD register | 396 | * __mmc_switch - modify EXT_CSD register |
| 371 | * @card: the MMC card associated with the data transfer | 397 | * @card: the MMC card associated with the data transfer |
| 372 | * @set: cmd set values | 398 | * @set: cmd set values |
| 373 | * @index: EXT_CSD register index | 399 | * @index: EXT_CSD register index |
| 374 | * @value: value to program into EXT_CSD register | 400 | * @value: value to program into EXT_CSD register |
| 375 | * @timeout_ms: timeout (ms) for operation performed by register write, | 401 | * @timeout_ms: timeout (ms) for operation performed by register write, |
| 376 | * timeout of zero implies maximum possible timeout | 402 | * timeout of zero implies maximum possible timeout |
| 403 | * @use_busy_signal: use the busy signal as response type | ||
| 377 | * | 404 | * |
| 378 | * Modifies the EXT_CSD register for selected card. | 405 | * Modifies the EXT_CSD register for selected card. |
| 379 | */ | 406 | */ |
| 380 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | 407 | int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, |
| 381 | unsigned int timeout_ms) | 408 | unsigned int timeout_ms, bool use_busy_signal) |
| 382 | { | 409 | { |
| 383 | int err; | 410 | int err; |
| 384 | struct mmc_command cmd = {0}; | 411 | struct mmc_command cmd = {0}; |
| @@ -392,13 +419,23 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | |||
| 392 | (index << 16) | | 419 | (index << 16) | |
| 393 | (value << 8) | | 420 | (value << 8) | |
| 394 | set; | 421 | set; |
| 395 | cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | 422 | cmd.flags = MMC_CMD_AC; |
| 423 | if (use_busy_signal) | ||
| 424 | cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; | ||
| 425 | else | ||
| 426 | cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; | ||
| 427 | |||
| 428 | |||
| 396 | cmd.cmd_timeout_ms = timeout_ms; | 429 | cmd.cmd_timeout_ms = timeout_ms; |
| 397 | 430 | ||
| 398 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); | 431 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); |
| 399 | if (err) | 432 | if (err) |
| 400 | return err; | 433 | return err; |
| 401 | 434 | ||
| 435 | /* No need to check card status in case of unblocking command */ | ||
| 436 | if (!use_busy_signal) | ||
| 437 | return 0; | ||
| 438 | |||
| 402 | /* Must check status to be sure of no errors */ | 439 | /* Must check status to be sure of no errors */ |
| 403 | do { | 440 | do { |
| 404 | err = mmc_send_status(card, &status); | 441 | err = mmc_send_status(card, &status); |
| @@ -423,6 +460,13 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | |||
| 423 | 460 | ||
| 424 | return 0; | 461 | return 0; |
| 425 | } | 462 | } |
| 463 | EXPORT_SYMBOL_GPL(__mmc_switch); | ||
| 464 | |||
| 465 | int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | ||
| 466 | unsigned int timeout_ms) | ||
| 467 | { | ||
| 468 | return __mmc_switch(card, set, index, value, timeout_ms, true); | ||
| 469 | } | ||
| 426 | EXPORT_SYMBOL_GPL(mmc_switch); | 470 | EXPORT_SYMBOL_GPL(mmc_switch); |
| 427 | 471 | ||
| 428 | int mmc_send_status(struct mmc_card *card, u32 *status) | 472 | int mmc_send_status(struct mmc_card *card, u32 *status) |
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 236842ec955a..6bf68799fe97 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c | |||
| @@ -193,14 +193,7 @@ static int sdio_bus_remove(struct device *dev) | |||
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | #ifdef CONFIG_PM | 195 | #ifdef CONFIG_PM |
| 196 | |||
| 197 | static int pm_no_operation(struct device *dev) | ||
| 198 | { | ||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | |||
| 202 | static const struct dev_pm_ops sdio_bus_pm_ops = { | 196 | static const struct dev_pm_ops sdio_bus_pm_ops = { |
| 203 | SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation) | ||
| 204 | SET_RUNTIME_PM_OPS( | 197 | SET_RUNTIME_PM_OPS( |
| 205 | pm_generic_runtime_suspend, | 198 | pm_generic_runtime_suspend, |
| 206 | pm_generic_runtime_resume, | 199 | pm_generic_runtime_resume, |
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 058242916cef..08c6b3dfe080 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c | |||
| @@ -100,7 +100,13 @@ int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) | |||
| 100 | 100 | ||
| 101 | ctx = host->slot.handler_priv; | 101 | ctx = host->slot.handler_priv; |
| 102 | 102 | ||
| 103 | return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label); | 103 | ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label); |
| 104 | if (ret < 0) | ||
| 105 | return ret; | ||
| 106 | |||
| 107 | ctx->ro_gpio = gpio; | ||
| 108 | |||
| 109 | return 0; | ||
| 104 | } | 110 | } |
| 105 | EXPORT_SYMBOL(mmc_gpio_request_ro); | 111 | EXPORT_SYMBOL(mmc_gpio_request_ro); |
| 106 | 112 | ||
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index aa131b32e3b2..9bf10e7bbfaf 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -540,6 +540,15 @@ config MMC_DW_PLTFM | |||
| 540 | 540 | ||
| 541 | If unsure, say Y. | 541 | If unsure, say Y. |
| 542 | 542 | ||
| 543 | config MMC_DW_EXYNOS | ||
| 544 | tristate "Exynos specific extentions for Synopsys DW Memory Card Interface" | ||
| 545 | depends on MMC_DW | ||
| 546 | select MMC_DW_PLTFM | ||
| 547 | help | ||
| 548 | This selects support for Samsung Exynos SoC specific extensions to the | ||
| 549 | Synopsys DesignWare Memory Card Interface driver. Select this option | ||
| 550 | for platforms based on Exynos4 and Exynos5 SoC's. | ||
| 551 | |||
| 543 | config MMC_DW_PCI | 552 | config MMC_DW_PCI |
| 544 | tristate "Synopsys Designware MCI support on PCI bus" | 553 | tristate "Synopsys Designware MCI support on PCI bus" |
| 545 | depends on MMC_DW && PCI | 554 | depends on MMC_DW && PCI |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 8922b06be925..17ad0a7ba40b 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
| @@ -39,6 +39,7 @@ obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o | |||
| 39 | obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o | 39 | obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o |
| 40 | obj-$(CONFIG_MMC_DW) += dw_mmc.o | 40 | obj-$(CONFIG_MMC_DW) += dw_mmc.o |
| 41 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o | 41 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o |
| 42 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o | ||
| 42 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o | 43 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o |
| 43 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o | 44 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o |
| 44 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o | 45 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o |
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h index ab56f7db5315..c97001e15227 100644 --- a/drivers/mmc/host/atmel-mci-regs.h +++ b/drivers/mmc/host/atmel-mci-regs.h | |||
| @@ -140,6 +140,13 @@ | |||
| 140 | #define atmci_writel(port,reg,value) \ | 140 | #define atmci_writel(port,reg,value) \ |
| 141 | __raw_writel((value), (port)->regs + reg) | 141 | __raw_writel((value), (port)->regs + reg) |
| 142 | 142 | ||
| 143 | /* On AVR chips the Peripheral DMA Controller is not connected to MCI. */ | ||
| 144 | #ifdef CONFIG_AVR32 | ||
| 145 | # define ATMCI_PDC_CONNECTED 0 | ||
| 146 | #else | ||
| 147 | # define ATMCI_PDC_CONNECTED 1 | ||
| 148 | #endif | ||
| 149 | |||
| 143 | /* | 150 | /* |
| 144 | * Fix sconfig's burst size according to atmel MCI. We need to convert them as: | 151 | * Fix sconfig's burst size according to atmel MCI. We need to convert them as: |
| 145 | * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. | 152 | * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 852d5fbda630..ddf096e3803f 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
| @@ -19,6 +19,9 @@ | |||
| 19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| 20 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/of.h> | ||
| 23 | #include <linux/of_device.h> | ||
| 24 | #include <linux/of_gpio.h> | ||
| 22 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 23 | #include <linux/scatterlist.h> | 26 | #include <linux/scatterlist.h> |
| 24 | #include <linux/seq_file.h> | 27 | #include <linux/seq_file.h> |
| @@ -71,7 +74,7 @@ enum atmci_pdc_buf { | |||
| 71 | }; | 74 | }; |
| 72 | 75 | ||
| 73 | struct atmel_mci_caps { | 76 | struct atmel_mci_caps { |
| 74 | bool has_dma; | 77 | bool has_dma_conf_reg; |
| 75 | bool has_pdc; | 78 | bool has_pdc; |
| 76 | bool has_cfg_reg; | 79 | bool has_cfg_reg; |
| 77 | bool has_cstor_reg; | 80 | bool has_cstor_reg; |
| @@ -418,7 +421,7 @@ static int atmci_regs_show(struct seq_file *s, void *v) | |||
| 418 | atmci_show_status_reg(s, "SR", buf[ATMCI_SR / 4]); | 421 | atmci_show_status_reg(s, "SR", buf[ATMCI_SR / 4]); |
| 419 | atmci_show_status_reg(s, "IMR", buf[ATMCI_IMR / 4]); | 422 | atmci_show_status_reg(s, "IMR", buf[ATMCI_IMR / 4]); |
| 420 | 423 | ||
| 421 | if (host->caps.has_dma) { | 424 | if (host->caps.has_dma_conf_reg) { |
| 422 | u32 val; | 425 | u32 val; |
| 423 | 426 | ||
| 424 | val = buf[ATMCI_DMA / 4]; | 427 | val = buf[ATMCI_DMA / 4]; |
| @@ -500,6 +503,70 @@ err: | |||
| 500 | dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); | 503 | dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); |
| 501 | } | 504 | } |
| 502 | 505 | ||
| 506 | #if defined(CONFIG_OF) | ||
| 507 | static const struct of_device_id atmci_dt_ids[] = { | ||
| 508 | { .compatible = "atmel,hsmci" }, | ||
| 509 | { /* sentinel */ } | ||
| 510 | }; | ||
| 511 | |||
| 512 | MODULE_DEVICE_TABLE(of, atmci_dt_ids); | ||
| 513 | |||
| 514 | static struct mci_platform_data __devinit* | ||
| 515 | atmci_of_init(struct platform_device *pdev) | ||
| 516 | { | ||
| 517 | struct device_node *np = pdev->dev.of_node; | ||
| 518 | struct device_node *cnp; | ||
| 519 | struct mci_platform_data *pdata; | ||
| 520 | u32 slot_id; | ||
| 521 | |||
| 522 | if (!np) { | ||
| 523 | dev_err(&pdev->dev, "device node not found\n"); | ||
| 524 | return ERR_PTR(-EINVAL); | ||
| 525 | } | ||
| 526 | |||
| 527 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
| 528 | if (!pdata) { | ||
| 529 | dev_err(&pdev->dev, "could not allocate memory for pdata\n"); | ||
| 530 | return ERR_PTR(-ENOMEM); | ||
| 531 | } | ||
| 532 | |||
| 533 | for_each_child_of_node(np, cnp) { | ||
| 534 | if (of_property_read_u32(cnp, "reg", &slot_id)) { | ||
| 535 | dev_warn(&pdev->dev, "reg property is missing for %s\n", | ||
| 536 | cnp->full_name); | ||
| 537 | continue; | ||
| 538 | } | ||
| 539 | |||
| 540 | if (slot_id >= ATMCI_MAX_NR_SLOTS) { | ||
| 541 | dev_warn(&pdev->dev, "can't have more than %d slots\n", | ||
| 542 | ATMCI_MAX_NR_SLOTS); | ||
| 543 | break; | ||
| 544 | } | ||
| 545 | |||
| 546 | if (of_property_read_u32(cnp, "bus-width", | ||
| 547 | &pdata->slot[slot_id].bus_width)) | ||
| 548 | pdata->slot[slot_id].bus_width = 1; | ||
| 549 | |||
| 550 | pdata->slot[slot_id].detect_pin = | ||
| 551 | of_get_named_gpio(cnp, "cd-gpios", 0); | ||
| 552 | |||
| 553 | pdata->slot[slot_id].detect_is_active_high = | ||
| 554 | of_property_read_bool(cnp, "cd-inverted"); | ||
| 555 | |||
| 556 | pdata->slot[slot_id].wp_pin = | ||
| 557 | of_get_named_gpio(cnp, "wp-gpios", 0); | ||
| 558 | } | ||
| 559 | |||
| 560 | return pdata; | ||
| 561 | } | ||
| 562 | #else /* CONFIG_OF */ | ||
| 563 | static inline struct mci_platform_data* | ||
| 564 | atmci_of_init(struct platform_device *dev) | ||
| 565 | { | ||
| 566 | return ERR_PTR(-EINVAL); | ||
| 567 | } | ||
| 568 | #endif | ||
| 569 | |||
| 503 | static inline unsigned int atmci_get_version(struct atmel_mci *host) | 570 | static inline unsigned int atmci_get_version(struct atmel_mci *host) |
| 504 | { | 571 | { |
| 505 | return atmci_readl(host, ATMCI_VERSION) & 0x00000fff; | 572 | return atmci_readl(host, ATMCI_VERSION) & 0x00000fff; |
| @@ -774,7 +841,7 @@ static void atmci_dma_complete(void *arg) | |||
| 774 | 841 | ||
| 775 | dev_vdbg(&host->pdev->dev, "DMA complete\n"); | 842 | dev_vdbg(&host->pdev->dev, "DMA complete\n"); |
| 776 | 843 | ||
| 777 | if (host->caps.has_dma) | 844 | if (host->caps.has_dma_conf_reg) |
| 778 | /* Disable DMA hardware handshaking on MCI */ | 845 | /* Disable DMA hardware handshaking on MCI */ |
| 779 | atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN); | 846 | atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN); |
| 780 | 847 | ||
| @@ -961,7 +1028,9 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) | |||
| 961 | maxburst = atmci_convert_chksize(host->dma_conf.dst_maxburst); | 1028 | maxburst = atmci_convert_chksize(host->dma_conf.dst_maxburst); |
| 962 | } | 1029 | } |
| 963 | 1030 | ||
| 964 | atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(maxburst) | ATMCI_DMAEN); | 1031 | if (host->caps.has_dma_conf_reg) |
| 1032 | atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(maxburst) | | ||
| 1033 | ATMCI_DMAEN); | ||
| 965 | 1034 | ||
| 966 | sglen = dma_map_sg(chan->device->dev, data->sg, | 1035 | sglen = dma_map_sg(chan->device->dev, data->sg, |
| 967 | data->sg_len, direction); | 1036 | data->sg_len, direction); |
| @@ -2046,6 +2115,13 @@ static int __init atmci_init_slot(struct atmel_mci *host, | |||
| 2046 | slot->sdc_reg = sdc_reg; | 2115 | slot->sdc_reg = sdc_reg; |
| 2047 | slot->sdio_irq = sdio_irq; | 2116 | slot->sdio_irq = sdio_irq; |
| 2048 | 2117 | ||
| 2118 | dev_dbg(&mmc->class_dev, | ||
| 2119 | "slot[%u]: bus_width=%u, detect_pin=%d, " | ||
| 2120 | "detect_is_active_high=%s, wp_pin=%d\n", | ||
| 2121 | id, slot_data->bus_width, slot_data->detect_pin, | ||
| 2122 | slot_data->detect_is_active_high ? "true" : "false", | ||
| 2123 | slot_data->wp_pin); | ||
| 2124 | |||
| 2049 | mmc->ops = &atmci_ops; | 2125 | mmc->ops = &atmci_ops; |
| 2050 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); | 2126 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); |
| 2051 | mmc->f_max = host->bus_hz / 2; | 2127 | mmc->f_max = host->bus_hz / 2; |
| @@ -2169,7 +2245,10 @@ static bool atmci_configure_dma(struct atmel_mci *host) | |||
| 2169 | 2245 | ||
| 2170 | pdata = host->pdev->dev.platform_data; | 2246 | pdata = host->pdev->dev.platform_data; |
| 2171 | 2247 | ||
| 2172 | if (pdata && find_slave_dev(pdata->dma_slave)) { | 2248 | if (!pdata) |
| 2249 | return false; | ||
| 2250 | |||
| 2251 | if (pdata->dma_slave && find_slave_dev(pdata->dma_slave)) { | ||
| 2173 | dma_cap_mask_t mask; | 2252 | dma_cap_mask_t mask; |
| 2174 | 2253 | ||
| 2175 | /* Try to grab a DMA channel */ | 2254 | /* Try to grab a DMA channel */ |
| @@ -2210,8 +2289,8 @@ static void __init atmci_get_cap(struct atmel_mci *host) | |||
| 2210 | dev_info(&host->pdev->dev, | 2289 | dev_info(&host->pdev->dev, |
| 2211 | "version: 0x%x\n", version); | 2290 | "version: 0x%x\n", version); |
| 2212 | 2291 | ||
| 2213 | host->caps.has_dma = 0; | 2292 | host->caps.has_dma_conf_reg = 0; |
| 2214 | host->caps.has_pdc = 1; | 2293 | host->caps.has_pdc = ATMCI_PDC_CONNECTED; |
| 2215 | host->caps.has_cfg_reg = 0; | 2294 | host->caps.has_cfg_reg = 0; |
| 2216 | host->caps.has_cstor_reg = 0; | 2295 | host->caps.has_cstor_reg = 0; |
| 2217 | host->caps.has_highspeed = 0; | 2296 | host->caps.has_highspeed = 0; |
| @@ -2228,12 +2307,7 @@ static void __init atmci_get_cap(struct atmel_mci *host) | |||
| 2228 | host->caps.has_odd_clk_div = 1; | 2307 | host->caps.has_odd_clk_div = 1; |
| 2229 | case 0x400: | 2308 | case 0x400: |
| 2230 | case 0x300: | 2309 | case 0x300: |
| 2231 | #ifdef CONFIG_AT_HDMAC | 2310 | host->caps.has_dma_conf_reg = 1; |
| 2232 | host->caps.has_dma = 1; | ||
| 2233 | #else | ||
| 2234 | dev_info(&host->pdev->dev, | ||
| 2235 | "has dma capability but dma engine is not selected, then use pio\n"); | ||
| 2236 | #endif | ||
| 2237 | host->caps.has_pdc = 0; | 2311 | host->caps.has_pdc = 0; |
| 2238 | host->caps.has_cfg_reg = 1; | 2312 | host->caps.has_cfg_reg = 1; |
| 2239 | host->caps.has_cstor_reg = 1; | 2313 | host->caps.has_cstor_reg = 1; |
| @@ -2268,8 +2342,14 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
| 2268 | if (!regs) | 2342 | if (!regs) |
| 2269 | return -ENXIO; | 2343 | return -ENXIO; |
| 2270 | pdata = pdev->dev.platform_data; | 2344 | pdata = pdev->dev.platform_data; |
| 2271 | if (!pdata) | 2345 | if (!pdata) { |
| 2272 | return -ENXIO; | 2346 | pdata = atmci_of_init(pdev); |
| 2347 | if (IS_ERR(pdata)) { | ||
| 2348 | dev_err(&pdev->dev, "platform data not available\n"); | ||
| 2349 | return PTR_ERR(pdata); | ||
| 2350 | } | ||
| 2351 | } | ||
| 2352 | |||
| 2273 | irq = platform_get_irq(pdev, 0); | 2353 | irq = platform_get_irq(pdev, 0); |
| 2274 | if (irq < 0) | 2354 | if (irq < 0) |
| 2275 | return irq; | 2355 | return irq; |
| @@ -2308,7 +2388,7 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
| 2308 | 2388 | ||
| 2309 | /* Get MCI capabilities and set operations according to it */ | 2389 | /* Get MCI capabilities and set operations according to it */ |
| 2310 | atmci_get_cap(host); | 2390 | atmci_get_cap(host); |
| 2311 | if (host->caps.has_dma && atmci_configure_dma(host)) { | 2391 | if (atmci_configure_dma(host)) { |
| 2312 | host->prepare_data = &atmci_prepare_data_dma; | 2392 | host->prepare_data = &atmci_prepare_data_dma; |
| 2313 | host->submit_data = &atmci_submit_data_dma; | 2393 | host->submit_data = &atmci_submit_data_dma; |
| 2314 | host->stop_transfer = &atmci_stop_transfer_dma; | 2394 | host->stop_transfer = &atmci_stop_transfer_dma; |
| @@ -2487,6 +2567,7 @@ static struct platform_driver atmci_driver = { | |||
| 2487 | .driver = { | 2567 | .driver = { |
| 2488 | .name = "atmel_mci", | 2568 | .name = "atmel_mci", |
| 2489 | .pm = ATMCI_PM_OPS, | 2569 | .pm = ATMCI_PM_OPS, |
| 2570 | .of_match_table = of_match_ptr(atmci_dt_ids), | ||
| 2490 | }, | 2571 | }, |
| 2491 | }; | 2572 | }; |
| 2492 | 2573 | ||
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index a17dd7363ceb..b9b463eca1ec 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c | |||
| @@ -24,9 +24,7 @@ | |||
| 24 | #include <asm/portmux.h> | 24 | #include <asm/portmux.h> |
| 25 | #include <asm/bfin_sdh.h> | 25 | #include <asm/bfin_sdh.h> |
| 26 | 26 | ||
| 27 | #if defined(CONFIG_BF51x) | 27 | #if defined(CONFIG_BF51x) || defined(__ADSPBF60x__) |
| 28 | #define bfin_read_SDH_PWR_CTL bfin_read_RSI_PWR_CTL | ||
| 29 | #define bfin_write_SDH_PWR_CTL bfin_write_RSI_PWR_CTL | ||
| 30 | #define bfin_read_SDH_CLK_CTL bfin_read_RSI_CLK_CTL | 28 | #define bfin_read_SDH_CLK_CTL bfin_read_RSI_CLK_CTL |
| 31 | #define bfin_write_SDH_CLK_CTL bfin_write_RSI_CLK_CTL | 29 | #define bfin_write_SDH_CLK_CTL bfin_write_RSI_CLK_CTL |
| 32 | #define bfin_write_SDH_ARGUMENT bfin_write_RSI_ARGUMENT | 30 | #define bfin_write_SDH_ARGUMENT bfin_write_RSI_ARGUMENT |
| @@ -45,8 +43,16 @@ | |||
| 45 | #define bfin_write_SDH_E_STATUS bfin_write_RSI_E_STATUS | 43 | #define bfin_write_SDH_E_STATUS bfin_write_RSI_E_STATUS |
| 46 | #define bfin_read_SDH_STATUS bfin_read_RSI_STATUS | 44 | #define bfin_read_SDH_STATUS bfin_read_RSI_STATUS |
| 47 | #define bfin_write_SDH_MASK0 bfin_write_RSI_MASK0 | 45 | #define bfin_write_SDH_MASK0 bfin_write_RSI_MASK0 |
| 46 | #define bfin_write_SDH_E_MASK bfin_write_RSI_E_MASK | ||
| 48 | #define bfin_read_SDH_CFG bfin_read_RSI_CFG | 47 | #define bfin_read_SDH_CFG bfin_read_RSI_CFG |
| 49 | #define bfin_write_SDH_CFG bfin_write_RSI_CFG | 48 | #define bfin_write_SDH_CFG bfin_write_RSI_CFG |
| 49 | # if defined(__ADSPBF60x__) | ||
| 50 | # define bfin_read_SDH_BLK_SIZE bfin_read_RSI_BLKSZ | ||
| 51 | # define bfin_write_SDH_BLK_SIZE bfin_write_RSI_BLKSZ | ||
| 52 | # else | ||
| 53 | # define bfin_read_SDH_PWR_CTL bfin_read_RSI_PWR_CTL | ||
| 54 | # define bfin_write_SDH_PWR_CTL bfin_write_RSI_PWR_CTL | ||
| 55 | # endif | ||
| 50 | #endif | 56 | #endif |
| 51 | 57 | ||
| 52 | struct sdh_host { | 58 | struct sdh_host { |
| @@ -62,6 +68,7 @@ struct sdh_host { | |||
| 62 | dma_addr_t sg_dma; | 68 | dma_addr_t sg_dma; |
| 63 | int dma_len; | 69 | int dma_len; |
| 64 | 70 | ||
| 71 | unsigned long sclk; | ||
| 65 | unsigned int imask; | 72 | unsigned int imask; |
| 66 | unsigned int power_mode; | 73 | unsigned int power_mode; |
| 67 | unsigned int clk_div; | 74 | unsigned int clk_div; |
| @@ -127,11 +134,15 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
| 127 | /* Only supports power-of-2 block size */ | 134 | /* Only supports power-of-2 block size */ |
| 128 | if (data->blksz & (data->blksz - 1)) | 135 | if (data->blksz & (data->blksz - 1)) |
| 129 | return -EINVAL; | 136 | return -EINVAL; |
| 137 | #ifndef RSI_BLKSZ | ||
| 130 | data_ctl |= ((ffs(data->blksz) - 1) << 4); | 138 | data_ctl |= ((ffs(data->blksz) - 1) << 4); |
| 139 | #else | ||
| 140 | bfin_write_SDH_BLK_SIZE(data->blksz); | ||
| 141 | #endif | ||
| 131 | 142 | ||
| 132 | bfin_write_SDH_DATA_CTL(data_ctl); | 143 | bfin_write_SDH_DATA_CTL(data_ctl); |
| 133 | /* the time of a host clock period in ns */ | 144 | /* the time of a host clock period in ns */ |
| 134 | cycle_ns = 1000000000 / (get_sclk() / (2 * (host->clk_div + 1))); | 145 | cycle_ns = 1000000000 / (host->sclk / (2 * (host->clk_div + 1))); |
| 135 | timeout = data->timeout_ns / cycle_ns; | 146 | timeout = data->timeout_ns / cycle_ns; |
| 136 | timeout += data->timeout_clks; | 147 | timeout += data->timeout_clks; |
| 137 | bfin_write_SDH_DATA_TIMER(timeout); | 148 | bfin_write_SDH_DATA_TIMER(timeout); |
| @@ -145,8 +156,13 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
| 145 | 156 | ||
| 146 | sdh_enable_stat_irq(host, (DAT_CRC_FAIL | DAT_TIME_OUT | DAT_END)); | 157 | sdh_enable_stat_irq(host, (DAT_CRC_FAIL | DAT_TIME_OUT | DAT_END)); |
| 147 | host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir); | 158 | host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir); |
| 148 | #if defined(CONFIG_BF54x) | 159 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) |
| 149 | dma_cfg |= DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_32 | DMAEN; | 160 | dma_cfg |= DMAFLOW_ARRAY | RESTART | WDSIZE_32 | DMAEN; |
| 161 | # ifdef RSI_BLKSZ | ||
| 162 | dma_cfg |= PSIZE_32 | NDSIZE_3; | ||
| 163 | # else | ||
| 164 | dma_cfg |= NDSIZE_5; | ||
| 165 | # endif | ||
| 150 | { | 166 | { |
| 151 | struct scatterlist *sg; | 167 | struct scatterlist *sg; |
| 152 | int i; | 168 | int i; |
| @@ -156,7 +172,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
| 156 | host->sg_cpu[i].x_count = sg_dma_len(sg) / 4; | 172 | host->sg_cpu[i].x_count = sg_dma_len(sg) / 4; |
| 157 | host->sg_cpu[i].x_modify = 4; | 173 | host->sg_cpu[i].x_modify = 4; |
| 158 | dev_dbg(mmc_dev(host->mmc), "%d: start_addr:0x%lx, " | 174 | dev_dbg(mmc_dev(host->mmc), "%d: start_addr:0x%lx, " |
| 159 | "cfg:0x%x, x_count:0x%x, x_modify:0x%x\n", | 175 | "cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n", |
| 160 | i, host->sg_cpu[i].start_addr, | 176 | i, host->sg_cpu[i].start_addr, |
| 161 | host->sg_cpu[i].cfg, host->sg_cpu[i].x_count, | 177 | host->sg_cpu[i].cfg, host->sg_cpu[i].x_count, |
| 162 | host->sg_cpu[i].x_modify); | 178 | host->sg_cpu[i].x_modify); |
| @@ -172,6 +188,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
| 172 | set_dma_curr_desc_addr(host->dma_ch, (unsigned long *)host->sg_dma); | 188 | set_dma_curr_desc_addr(host->dma_ch, (unsigned long *)host->sg_dma); |
| 173 | set_dma_x_count(host->dma_ch, 0); | 189 | set_dma_x_count(host->dma_ch, 0); |
| 174 | set_dma_x_modify(host->dma_ch, 0); | 190 | set_dma_x_modify(host->dma_ch, 0); |
| 191 | SSYNC(); | ||
| 175 | set_dma_config(host->dma_ch, dma_cfg); | 192 | set_dma_config(host->dma_ch, dma_cfg); |
| 176 | #elif defined(CONFIG_BF51x) | 193 | #elif defined(CONFIG_BF51x) |
| 177 | /* RSI DMA doesn't work in array mode */ | 194 | /* RSI DMA doesn't work in array mode */ |
| @@ -179,6 +196,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
| 179 | set_dma_start_addr(host->dma_ch, sg_dma_address(&data->sg[0])); | 196 | set_dma_start_addr(host->dma_ch, sg_dma_address(&data->sg[0])); |
| 180 | set_dma_x_count(host->dma_ch, length / 4); | 197 | set_dma_x_count(host->dma_ch, length / 4); |
| 181 | set_dma_x_modify(host->dma_ch, 4); | 198 | set_dma_x_modify(host->dma_ch, 4); |
| 199 | SSYNC(); | ||
| 182 | set_dma_config(host->dma_ch, dma_cfg); | 200 | set_dma_config(host->dma_ch, dma_cfg); |
| 183 | #endif | 201 | #endif |
| 184 | bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E); | 202 | bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E); |
| @@ -296,7 +314,6 @@ static int sdh_data_done(struct sdh_host *host, unsigned int stat) | |||
| 296 | else | 314 | else |
| 297 | data->bytes_xfered = 0; | 315 | data->bytes_xfered = 0; |
| 298 | 316 | ||
| 299 | sdh_disable_stat_irq(host, DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN); | ||
| 300 | bfin_write_SDH_STATUS_CLR(DAT_END_STAT | DAT_TIMEOUT_STAT | \ | 317 | bfin_write_SDH_STATUS_CLR(DAT_END_STAT | DAT_TIMEOUT_STAT | \ |
| 301 | DAT_CRC_FAIL_STAT | DAT_BLK_END_STAT | RX_OVERRUN | TX_UNDERRUN); | 318 | DAT_CRC_FAIL_STAT | DAT_BLK_END_STAT | RX_OVERRUN | TX_UNDERRUN); |
| 302 | bfin_write_SDH_DATA_CTL(0); | 319 | bfin_write_SDH_DATA_CTL(0); |
| @@ -321,74 +338,115 @@ static void sdh_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 321 | dev_dbg(mmc_dev(host->mmc), "%s enter, mrp:%p, cmd:%p\n", __func__, mrq, mrq->cmd); | 338 | dev_dbg(mmc_dev(host->mmc), "%s enter, mrp:%p, cmd:%p\n", __func__, mrq, mrq->cmd); |
| 322 | WARN_ON(host->mrq != NULL); | 339 | WARN_ON(host->mrq != NULL); |
| 323 | 340 | ||
| 341 | spin_lock(&host->lock); | ||
| 324 | host->mrq = mrq; | 342 | host->mrq = mrq; |
| 325 | host->data = mrq->data; | 343 | host->data = mrq->data; |
| 326 | 344 | ||
| 327 | if (mrq->data && mrq->data->flags & MMC_DATA_READ) { | 345 | if (mrq->data && mrq->data->flags & MMC_DATA_READ) { |
| 328 | ret = sdh_setup_data(host, mrq->data); | 346 | ret = sdh_setup_data(host, mrq->data); |
| 329 | if (ret) | 347 | if (ret) |
| 330 | return; | 348 | goto data_err; |
| 331 | } | 349 | } |
| 332 | 350 | ||
| 333 | sdh_start_cmd(host, mrq->cmd); | 351 | sdh_start_cmd(host, mrq->cmd); |
| 352 | data_err: | ||
| 353 | spin_unlock(&host->lock); | ||
| 334 | } | 354 | } |
| 335 | 355 | ||
| 336 | static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | 356 | static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
| 337 | { | 357 | { |
| 338 | struct sdh_host *host; | 358 | struct sdh_host *host; |
| 339 | unsigned long flags; | ||
| 340 | u16 clk_ctl = 0; | 359 | u16 clk_ctl = 0; |
| 360 | #ifndef RSI_BLKSZ | ||
| 341 | u16 pwr_ctl = 0; | 361 | u16 pwr_ctl = 0; |
| 362 | #endif | ||
| 342 | u16 cfg; | 363 | u16 cfg; |
| 343 | host = mmc_priv(mmc); | 364 | host = mmc_priv(mmc); |
| 344 | 365 | ||
| 345 | spin_lock_irqsave(&host->lock, flags); | 366 | spin_lock(&host->lock); |
| 346 | if (ios->clock) { | ||
| 347 | unsigned long sys_clk, ios_clk; | ||
| 348 | unsigned char clk_div; | ||
| 349 | ios_clk = 2 * ios->clock; | ||
| 350 | sys_clk = get_sclk(); | ||
| 351 | clk_div = sys_clk / ios_clk; | ||
| 352 | if (sys_clk % ios_clk == 0) | ||
| 353 | clk_div -= 1; | ||
| 354 | clk_div = min_t(unsigned char, clk_div, 0xFF); | ||
| 355 | clk_ctl |= clk_div; | ||
| 356 | clk_ctl |= CLK_E; | ||
| 357 | host->clk_div = clk_div; | ||
| 358 | } else | ||
| 359 | sdh_stop_clock(host); | ||
| 360 | |||
| 361 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) | ||
| 362 | #ifdef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND | ||
| 363 | pwr_ctl |= ROD_CTL; | ||
| 364 | #else | ||
| 365 | pwr_ctl |= SD_CMD_OD | ROD_CTL; | ||
| 366 | #endif | ||
| 367 | 367 | ||
| 368 | if (ios->bus_width == MMC_BUS_WIDTH_4) { | 368 | cfg = bfin_read_SDH_CFG(); |
| 369 | cfg = bfin_read_SDH_CFG(); | 369 | cfg |= MWE; |
| 370 | switch (ios->bus_width) { | ||
| 371 | case MMC_BUS_WIDTH_4: | ||
| 372 | #ifndef RSI_BLKSZ | ||
| 370 | cfg &= ~PD_SDDAT3; | 373 | cfg &= ~PD_SDDAT3; |
| 374 | #endif | ||
| 371 | cfg |= PUP_SDDAT3; | 375 | cfg |= PUP_SDDAT3; |
| 372 | /* Enable 4 bit SDIO */ | 376 | /* Enable 4 bit SDIO */ |
| 373 | cfg |= (SD4E | MWE); | 377 | cfg |= SD4E; |
| 374 | bfin_write_SDH_CFG(cfg); | 378 | clk_ctl |= WIDE_BUS_4; |
| 375 | clk_ctl |= WIDE_BUS; | 379 | break; |
| 376 | } else { | 380 | case MMC_BUS_WIDTH_8: |
| 377 | cfg = bfin_read_SDH_CFG(); | 381 | #ifndef RSI_BLKSZ |
| 378 | cfg |= MWE; | 382 | cfg &= ~PD_SDDAT3; |
| 379 | bfin_write_SDH_CFG(cfg); | 383 | #endif |
| 384 | cfg |= PUP_SDDAT3; | ||
| 385 | /* Disable 4 bit SDIO */ | ||
| 386 | cfg &= ~SD4E; | ||
| 387 | clk_ctl |= BYTE_BUS_8; | ||
| 388 | break; | ||
| 389 | default: | ||
| 390 | cfg &= ~PUP_SDDAT3; | ||
| 391 | /* Disable 4 bit SDIO */ | ||
| 392 | cfg &= ~SD4E; | ||
| 380 | } | 393 | } |
| 381 | 394 | ||
| 382 | bfin_write_SDH_CLK_CTL(clk_ctl); | ||
| 383 | |||
| 384 | host->power_mode = ios->power_mode; | 395 | host->power_mode = ios->power_mode; |
| 385 | if (ios->power_mode == MMC_POWER_ON) | 396 | #ifndef RSI_BLKSZ |
| 397 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { | ||
| 398 | pwr_ctl |= ROD_CTL; | ||
| 399 | # ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND | ||
| 400 | pwr_ctl |= SD_CMD_OD; | ||
| 401 | # endif | ||
| 402 | } | ||
| 403 | |||
| 404 | if (ios->power_mode != MMC_POWER_OFF) | ||
| 386 | pwr_ctl |= PWR_ON; | 405 | pwr_ctl |= PWR_ON; |
| 406 | else | ||
| 407 | pwr_ctl &= ~PWR_ON; | ||
| 387 | 408 | ||
| 388 | bfin_write_SDH_PWR_CTL(pwr_ctl); | 409 | bfin_write_SDH_PWR_CTL(pwr_ctl); |
| 410 | #else | ||
| 411 | # ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND | ||
| 412 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) | ||
| 413 | cfg |= SD_CMD_OD; | ||
| 414 | else | ||
| 415 | cfg &= ~SD_CMD_OD; | ||
| 416 | # endif | ||
| 417 | |||
| 418 | |||
| 419 | if (ios->power_mode != MMC_POWER_OFF) | ||
| 420 | cfg |= PWR_ON; | ||
| 421 | else | ||
| 422 | cfg &= ~PWR_ON; | ||
| 423 | |||
| 424 | bfin_write_SDH_CFG(cfg); | ||
| 425 | #endif | ||
| 389 | SSYNC(); | 426 | SSYNC(); |
| 390 | 427 | ||
| 391 | spin_unlock_irqrestore(&host->lock, flags); | 428 | if (ios->power_mode == MMC_POWER_ON && ios->clock) { |
| 429 | unsigned char clk_div; | ||
| 430 | clk_div = (get_sclk() / ios->clock - 1) / 2; | ||
| 431 | clk_div = min_t(unsigned char, clk_div, 0xFF); | ||
| 432 | clk_ctl |= clk_div; | ||
| 433 | clk_ctl |= CLK_E; | ||
| 434 | host->clk_div = clk_div; | ||
| 435 | bfin_write_SDH_CLK_CTL(clk_ctl); | ||
| 436 | |||
| 437 | } else | ||
| 438 | sdh_stop_clock(host); | ||
| 439 | |||
| 440 | /* set up sdh interrupt mask*/ | ||
| 441 | if (ios->power_mode == MMC_POWER_ON) | ||
| 442 | bfin_write_SDH_MASK0(DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | | ||
| 443 | RX_OVERRUN | TX_UNDERRUN | CMD_SENT | CMD_RESP_END | | ||
| 444 | CMD_TIME_OUT | CMD_CRC_FAIL); | ||
| 445 | else | ||
| 446 | bfin_write_SDH_MASK0(0); | ||
| 447 | SSYNC(); | ||
| 448 | |||
| 449 | spin_unlock(&host->lock); | ||
| 392 | 450 | ||
| 393 | dev_dbg(mmc_dev(host->mmc), "SDH: clk_div = 0x%x actual clock:%ld expected clock:%d\n", | 451 | dev_dbg(mmc_dev(host->mmc), "SDH: clk_div = 0x%x actual clock:%ld expected clock:%d\n", |
| 394 | host->clk_div, | 452 | host->clk_div, |
| @@ -405,7 +463,7 @@ static irqreturn_t sdh_dma_irq(int irq, void *devid) | |||
| 405 | { | 463 | { |
| 406 | struct sdh_host *host = devid; | 464 | struct sdh_host *host = devid; |
| 407 | 465 | ||
| 408 | dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04x\n", __func__, | 466 | dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04lx\n", __func__, |
| 409 | get_dma_curr_irqstat(host->dma_ch)); | 467 | get_dma_curr_irqstat(host->dma_ch)); |
| 410 | clear_dma_irqstat(host->dma_ch); | 468 | clear_dma_irqstat(host->dma_ch); |
| 411 | SSYNC(); | 469 | SSYNC(); |
| @@ -420,6 +478,9 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid) | |||
| 420 | int handled = 0; | 478 | int handled = 0; |
| 421 | 479 | ||
| 422 | dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__); | 480 | dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__); |
| 481 | |||
| 482 | spin_lock(&host->lock); | ||
| 483 | |||
| 423 | status = bfin_read_SDH_E_STATUS(); | 484 | status = bfin_read_SDH_E_STATUS(); |
| 424 | if (status & SD_CARD_DET) { | 485 | if (status & SD_CARD_DET) { |
| 425 | mmc_detect_change(host->mmc, 0); | 486 | mmc_detect_change(host->mmc, 0); |
| @@ -437,11 +498,30 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid) | |||
| 437 | if (status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN)) | 498 | if (status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN)) |
| 438 | handled |= sdh_data_done(host, status); | 499 | handled |= sdh_data_done(host, status); |
| 439 | 500 | ||
| 501 | spin_unlock(&host->lock); | ||
| 502 | |||
| 440 | dev_dbg(mmc_dev(host->mmc), "%s exit\n\n", __func__); | 503 | dev_dbg(mmc_dev(host->mmc), "%s exit\n\n", __func__); |
| 441 | 504 | ||
| 442 | return IRQ_RETVAL(handled); | 505 | return IRQ_RETVAL(handled); |
| 443 | } | 506 | } |
| 444 | 507 | ||
| 508 | static void sdh_reset(void) | ||
| 509 | { | ||
| 510 | #if defined(CONFIG_BF54x) | ||
| 511 | /* Secure Digital Host shares DMA with Nand controller */ | ||
| 512 | bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); | ||
| 513 | #endif | ||
| 514 | |||
| 515 | bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); | ||
| 516 | SSYNC(); | ||
| 517 | |||
| 518 | /* Disable card inserting detection pin. set MMC_CAP_NEEDS_POLL, and | ||
| 519 | * mmc stack will do the detection. | ||
| 520 | */ | ||
| 521 | bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); | ||
| 522 | SSYNC(); | ||
| 523 | } | ||
| 524 | |||
| 445 | static int __devinit sdh_probe(struct platform_device *pdev) | 525 | static int __devinit sdh_probe(struct platform_device *pdev) |
| 446 | { | 526 | { |
| 447 | struct mmc_host *mmc; | 527 | struct mmc_host *mmc; |
| @@ -462,8 +542,16 @@ static int __devinit sdh_probe(struct platform_device *pdev) | |||
| 462 | } | 542 | } |
| 463 | 543 | ||
| 464 | mmc->ops = &sdh_ops; | 544 | mmc->ops = &sdh_ops; |
| 465 | mmc->max_segs = 32; | 545 | #if defined(CONFIG_BF51x) |
| 546 | mmc->max_segs = 1; | ||
| 547 | #else | ||
| 548 | mmc->max_segs = PAGE_SIZE / sizeof(struct dma_desc_array); | ||
| 549 | #endif | ||
| 550 | #ifdef RSI_BLKSZ | ||
| 551 | mmc->max_seg_size = -1; | ||
| 552 | #else | ||
| 466 | mmc->max_seg_size = 1 << 16; | 553 | mmc->max_seg_size = 1 << 16; |
| 554 | #endif | ||
| 467 | mmc->max_blk_size = 1 << 11; | 555 | mmc->max_blk_size = 1 << 11; |
| 468 | mmc->max_blk_count = 1 << 11; | 556 | mmc->max_blk_count = 1 << 11; |
| 469 | mmc->max_req_size = PAGE_SIZE; | 557 | mmc->max_req_size = PAGE_SIZE; |
| @@ -473,6 +561,7 @@ static int __devinit sdh_probe(struct platform_device *pdev) | |||
| 473 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL; | 561 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL; |
| 474 | host = mmc_priv(mmc); | 562 | host = mmc_priv(mmc); |
| 475 | host->mmc = mmc; | 563 | host->mmc = mmc; |
| 564 | host->sclk = get_sclk(); | ||
| 476 | 565 | ||
| 477 | spin_lock_init(&host->lock); | 566 | spin_lock_init(&host->lock); |
| 478 | host->irq = drv_data->irq_int0; | 567 | host->irq = drv_data->irq_int0; |
| @@ -497,7 +586,6 @@ static int __devinit sdh_probe(struct platform_device *pdev) | |||
| 497 | } | 586 | } |
| 498 | 587 | ||
| 499 | platform_set_drvdata(pdev, mmc); | 588 | platform_set_drvdata(pdev, mmc); |
| 500 | mmc_add_host(mmc); | ||
| 501 | 589 | ||
| 502 | ret = request_irq(host->irq, sdh_stat_irq, 0, "SDH Status IRQ", host); | 590 | ret = request_irq(host->irq, sdh_stat_irq, 0, "SDH Status IRQ", host); |
| 503 | if (ret) { | 591 | if (ret) { |
| @@ -510,20 +598,10 @@ static int __devinit sdh_probe(struct platform_device *pdev) | |||
| 510 | dev_err(&pdev->dev, "unable to request peripheral pins\n"); | 598 | dev_err(&pdev->dev, "unable to request peripheral pins\n"); |
| 511 | goto out4; | 599 | goto out4; |
| 512 | } | 600 | } |
| 513 | #if defined(CONFIG_BF54x) | ||
| 514 | /* Secure Digital Host shares DMA with Nand controller */ | ||
| 515 | bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); | ||
| 516 | #endif | ||
| 517 | |||
| 518 | bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); | ||
| 519 | SSYNC(); | ||
| 520 | 601 | ||
| 521 | /* Disable card inserting detection pin. set MMC_CAP_NEES_POLL, and | 602 | sdh_reset(); |
| 522 | * mmc stack will do the detection. | ||
| 523 | */ | ||
| 524 | bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); | ||
| 525 | SSYNC(); | ||
| 526 | 603 | ||
| 604 | mmc_add_host(mmc); | ||
| 527 | return 0; | 605 | return 0; |
| 528 | 606 | ||
| 529 | out4: | 607 | out4: |
| @@ -571,7 +649,6 @@ static int sdh_suspend(struct platform_device *dev, pm_message_t state) | |||
| 571 | if (mmc) | 649 | if (mmc) |
| 572 | ret = mmc_suspend_host(mmc); | 650 | ret = mmc_suspend_host(mmc); |
| 573 | 651 | ||
| 574 | bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() & ~PWR_ON); | ||
| 575 | peripheral_free_list(drv_data->pin_req); | 652 | peripheral_free_list(drv_data->pin_req); |
| 576 | 653 | ||
| 577 | return ret; | 654 | return ret; |
| @@ -589,16 +666,7 @@ static int sdh_resume(struct platform_device *dev) | |||
| 589 | return ret; | 666 | return ret; |
| 590 | } | 667 | } |
| 591 | 668 | ||
| 592 | bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() | PWR_ON); | 669 | sdh_reset(); |
| 593 | #if defined(CONFIG_BF54x) | ||
| 594 | /* Secure Digital Host shares DMA with Nand controller */ | ||
| 595 | bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); | ||
| 596 | #endif | ||
| 597 | bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); | ||
| 598 | SSYNC(); | ||
| 599 | |||
| 600 | bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); | ||
| 601 | SSYNC(); | ||
| 602 | 670 | ||
| 603 | if (mmc) | 671 | if (mmc) |
| 604 | ret = mmc_resume_host(mmc); | 672 | ret = mmc_resume_host(mmc); |
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 3dfd3473269d..20636772c09b 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c | |||
| @@ -30,11 +30,12 @@ | |||
| 30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
| 31 | #include <linux/irq.h> | 31 | #include <linux/irq.h> |
| 32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
| 33 | #include <linux/dmaengine.h> | ||
| 33 | #include <linux/dma-mapping.h> | 34 | #include <linux/dma-mapping.h> |
| 35 | #include <linux/edma.h> | ||
| 34 | #include <linux/mmc/mmc.h> | 36 | #include <linux/mmc/mmc.h> |
| 35 | 37 | ||
| 36 | #include <linux/platform_data/mmc-davinci.h> | 38 | #include <linux/platform_data/mmc-davinci.h> |
| 37 | #include <mach/edma.h> | ||
| 38 | 39 | ||
| 39 | /* | 40 | /* |
| 40 | * Register Definitions | 41 | * Register Definitions |
| @@ -200,21 +201,13 @@ struct mmc_davinci_host { | |||
| 200 | u32 bytes_left; | 201 | u32 bytes_left; |
| 201 | 202 | ||
| 202 | u32 rxdma, txdma; | 203 | u32 rxdma, txdma; |
| 204 | struct dma_chan *dma_tx; | ||
| 205 | struct dma_chan *dma_rx; | ||
| 203 | bool use_dma; | 206 | bool use_dma; |
| 204 | bool do_dma; | 207 | bool do_dma; |
| 205 | bool sdio_int; | 208 | bool sdio_int; |
| 206 | bool active_request; | 209 | bool active_request; |
| 207 | 210 | ||
| 208 | /* Scatterlist DMA uses one or more parameter RAM entries: | ||
| 209 | * the main one (associated with rxdma or txdma) plus zero or | ||
| 210 | * more links. The entries for a given transfer differ only | ||
| 211 | * by memory buffer (address, length) and link field. | ||
| 212 | */ | ||
| 213 | struct edmacc_param tx_template; | ||
| 214 | struct edmacc_param rx_template; | ||
| 215 | unsigned n_link; | ||
| 216 | u32 links[MAX_NR_SG - 1]; | ||
| 217 | |||
| 218 | /* For PIO we walk scatterlists one segment at a time. */ | 211 | /* For PIO we walk scatterlists one segment at a time. */ |
| 219 | unsigned int sg_len; | 212 | unsigned int sg_len; |
| 220 | struct scatterlist *sg; | 213 | struct scatterlist *sg; |
| @@ -410,153 +403,74 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host, | |||
| 410 | 403 | ||
| 411 | static void davinci_abort_dma(struct mmc_davinci_host *host) | 404 | static void davinci_abort_dma(struct mmc_davinci_host *host) |
| 412 | { | 405 | { |
| 413 | int sync_dev; | 406 | struct dma_chan *sync_dev; |
| 414 | 407 | ||
| 415 | if (host->data_dir == DAVINCI_MMC_DATADIR_READ) | 408 | if (host->data_dir == DAVINCI_MMC_DATADIR_READ) |
| 416 | sync_dev = host->rxdma; | 409 | sync_dev = host->dma_rx; |
| 417 | else | 410 | else |
| 418 | sync_dev = host->txdma; | 411 | sync_dev = host->dma_tx; |
| 419 | |||
| 420 | edma_stop(sync_dev); | ||
| 421 | edma_clean_channel(sync_dev); | ||
| 422 | } | ||
| 423 | |||
| 424 | static void | ||
| 425 | mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data); | ||
| 426 | |||
| 427 | static void mmc_davinci_dma_cb(unsigned channel, u16 ch_status, void *data) | ||
| 428 | { | ||
| 429 | if (DMA_COMPLETE != ch_status) { | ||
| 430 | struct mmc_davinci_host *host = data; | ||
| 431 | |||
| 432 | /* Currently means: DMA Event Missed, or "null" transfer | ||
| 433 | * request was seen. In the future, TC errors (like bad | ||
| 434 | * addresses) might be presented too. | ||
| 435 | */ | ||
| 436 | dev_warn(mmc_dev(host->mmc), "DMA %s error\n", | ||
| 437 | (host->data->flags & MMC_DATA_WRITE) | ||
| 438 | ? "write" : "read"); | ||
| 439 | host->data->error = -EIO; | ||
| 440 | mmc_davinci_xfer_done(host, host->data); | ||
| 441 | } | ||
| 442 | } | ||
| 443 | |||
| 444 | /* Set up tx or rx template, to be modified and updated later */ | ||
| 445 | static void __init mmc_davinci_dma_setup(struct mmc_davinci_host *host, | ||
| 446 | bool tx, struct edmacc_param *template) | ||
| 447 | { | ||
| 448 | unsigned sync_dev; | ||
| 449 | const u16 acnt = 4; | ||
| 450 | const u16 bcnt = rw_threshold >> 2; | ||
| 451 | const u16 ccnt = 0; | ||
| 452 | u32 src_port = 0; | ||
| 453 | u32 dst_port = 0; | ||
| 454 | s16 src_bidx, dst_bidx; | ||
| 455 | s16 src_cidx, dst_cidx; | ||
| 456 | |||
| 457 | /* | ||
| 458 | * A-B Sync transfer: each DMA request is for one "frame" of | ||
| 459 | * rw_threshold bytes, broken into "acnt"-size chunks repeated | ||
| 460 | * "bcnt" times. Each segment needs "ccnt" such frames; since | ||
| 461 | * we tell the block layer our mmc->max_seg_size limit, we can | ||
| 462 | * trust (later) that it's within bounds. | ||
| 463 | * | ||
| 464 | * The FIFOs are read/written in 4-byte chunks (acnt == 4) and | ||
| 465 | * EDMA will optimize memory operations to use larger bursts. | ||
| 466 | */ | ||
| 467 | if (tx) { | ||
| 468 | sync_dev = host->txdma; | ||
| 469 | |||
| 470 | /* src_prt, ccnt, and link to be set up later */ | ||
| 471 | src_bidx = acnt; | ||
| 472 | src_cidx = acnt * bcnt; | ||
| 473 | |||
| 474 | dst_port = host->mem_res->start + DAVINCI_MMCDXR; | ||
| 475 | dst_bidx = 0; | ||
| 476 | dst_cidx = 0; | ||
| 477 | } else { | ||
| 478 | sync_dev = host->rxdma; | ||
| 479 | |||
| 480 | src_port = host->mem_res->start + DAVINCI_MMCDRR; | ||
| 481 | src_bidx = 0; | ||
| 482 | src_cidx = 0; | ||
| 483 | |||
| 484 | /* dst_prt, ccnt, and link to be set up later */ | ||
| 485 | dst_bidx = acnt; | ||
| 486 | dst_cidx = acnt * bcnt; | ||
| 487 | } | ||
| 488 | |||
| 489 | /* | ||
| 490 | * We can't use FIFO mode for the FIFOs because MMC FIFO addresses | ||
| 491 | * are not 256-bit (32-byte) aligned. So we use INCR, and the W8BIT | ||
| 492 | * parameter is ignored. | ||
| 493 | */ | ||
| 494 | edma_set_src(sync_dev, src_port, INCR, W8BIT); | ||
| 495 | edma_set_dest(sync_dev, dst_port, INCR, W8BIT); | ||
| 496 | 412 | ||
| 497 | edma_set_src_index(sync_dev, src_bidx, src_cidx); | 413 | dmaengine_terminate_all(sync_dev); |
| 498 | edma_set_dest_index(sync_dev, dst_bidx, dst_cidx); | ||
| 499 | |||
| 500 | edma_set_transfer_params(sync_dev, acnt, bcnt, ccnt, 8, ABSYNC); | ||
| 501 | |||
| 502 | edma_read_slot(sync_dev, template); | ||
| 503 | |||
| 504 | /* don't bother with irqs or chaining */ | ||
| 505 | template->opt |= EDMA_CHAN_SLOT(sync_dev) << 12; | ||
| 506 | } | 414 | } |
| 507 | 415 | ||
| 508 | static void mmc_davinci_send_dma_request(struct mmc_davinci_host *host, | 416 | static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host, |
| 509 | struct mmc_data *data) | 417 | struct mmc_data *data) |
| 510 | { | 418 | { |
| 511 | struct edmacc_param *template; | 419 | struct dma_chan *chan; |
| 512 | int channel, slot; | 420 | struct dma_async_tx_descriptor *desc; |
| 513 | unsigned link; | 421 | int ret = 0; |
| 514 | struct scatterlist *sg; | ||
| 515 | unsigned sg_len; | ||
| 516 | unsigned bytes_left = host->bytes_left; | ||
| 517 | const unsigned shift = ffs(rw_threshold) - 1; | ||
| 518 | 422 | ||
| 519 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { | 423 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { |
| 520 | template = &host->tx_template; | 424 | struct dma_slave_config dma_tx_conf = { |
| 521 | channel = host->txdma; | 425 | .direction = DMA_MEM_TO_DEV, |
| 426 | .dst_addr = host->mem_res->start + DAVINCI_MMCDXR, | ||
| 427 | .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, | ||
| 428 | .dst_maxburst = | ||
| 429 | rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES, | ||
| 430 | }; | ||
| 431 | chan = host->dma_tx; | ||
| 432 | dmaengine_slave_config(host->dma_tx, &dma_tx_conf); | ||
| 433 | |||
| 434 | desc = dmaengine_prep_slave_sg(host->dma_tx, | ||
| 435 | data->sg, | ||
| 436 | host->sg_len, | ||
| 437 | DMA_MEM_TO_DEV, | ||
| 438 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
| 439 | if (!desc) { | ||
| 440 | dev_dbg(mmc_dev(host->mmc), | ||
| 441 | "failed to allocate DMA TX descriptor"); | ||
| 442 | ret = -1; | ||
| 443 | goto out; | ||
| 444 | } | ||
| 522 | } else { | 445 | } else { |
| 523 | template = &host->rx_template; | 446 | struct dma_slave_config dma_rx_conf = { |
| 524 | channel = host->rxdma; | 447 | .direction = DMA_DEV_TO_MEM, |
| 525 | } | 448 | .src_addr = host->mem_res->start + DAVINCI_MMCDRR, |
| 526 | 449 | .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, | |
| 527 | /* We know sg_len and ccnt will never be out of range because | 450 | .src_maxburst = |
| 528 | * we told the mmc layer which in turn tells the block layer | 451 | rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES, |
| 529 | * to ensure that it only hands us one scatterlist segment | 452 | }; |
| 530 | * per EDMA PARAM entry. Update the PARAM | 453 | chan = host->dma_rx; |
| 531 | * entries needed for each segment of this scatterlist. | 454 | dmaengine_slave_config(host->dma_rx, &dma_rx_conf); |
| 532 | */ | 455 | |
| 533 | for (slot = channel, link = 0, sg = data->sg, sg_len = host->sg_len; | 456 | desc = dmaengine_prep_slave_sg(host->dma_rx, |
| 534 | sg_len-- != 0 && bytes_left; | 457 | data->sg, |
| 535 | sg = sg_next(sg), slot = host->links[link++]) { | 458 | host->sg_len, |
| 536 | u32 buf = sg_dma_address(sg); | 459 | DMA_DEV_TO_MEM, |
| 537 | unsigned count = sg_dma_len(sg); | 460 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
| 538 | 461 | if (!desc) { | |
| 539 | template->link_bcntrld = sg_len | 462 | dev_dbg(mmc_dev(host->mmc), |
| 540 | ? (EDMA_CHAN_SLOT(host->links[link]) << 5) | 463 | "failed to allocate DMA RX descriptor"); |
| 541 | : 0xffff; | 464 | ret = -1; |
| 542 | 465 | goto out; | |
| 543 | if (count > bytes_left) | 466 | } |
| 544 | count = bytes_left; | ||
| 545 | bytes_left -= count; | ||
| 546 | |||
| 547 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) | ||
| 548 | template->src = buf; | ||
| 549 | else | ||
| 550 | template->dst = buf; | ||
| 551 | template->ccnt = count >> shift; | ||
| 552 | |||
| 553 | edma_write_slot(slot, template); | ||
| 554 | } | 467 | } |
| 555 | 468 | ||
| 556 | if (host->version == MMC_CTLR_VERSION_2) | 469 | dmaengine_submit(desc); |
| 557 | edma_clear_event(channel); | 470 | dma_async_issue_pending(chan); |
| 558 | 471 | ||
| 559 | edma_start(channel); | 472 | out: |
| 473 | return ret; | ||
| 560 | } | 474 | } |
| 561 | 475 | ||
| 562 | static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, | 476 | static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, |
| @@ -564,6 +478,7 @@ static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, | |||
| 564 | { | 478 | { |
| 565 | int i; | 479 | int i; |
| 566 | int mask = rw_threshold - 1; | 480 | int mask = rw_threshold - 1; |
| 481 | int ret = 0; | ||
| 567 | 482 | ||
| 568 | host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, | 483 | host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, |
| 569 | ((data->flags & MMC_DATA_WRITE) | 484 | ((data->flags & MMC_DATA_WRITE) |
| @@ -583,70 +498,48 @@ static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, | |||
| 583 | } | 498 | } |
| 584 | 499 | ||
| 585 | host->do_dma = 1; | 500 | host->do_dma = 1; |
| 586 | mmc_davinci_send_dma_request(host, data); | 501 | ret = mmc_davinci_send_dma_request(host, data); |
| 587 | 502 | ||
| 588 | return 0; | 503 | return ret; |
| 589 | } | 504 | } |
| 590 | 505 | ||
| 591 | static void __init_or_module | 506 | static void __init_or_module |
| 592 | davinci_release_dma_channels(struct mmc_davinci_host *host) | 507 | davinci_release_dma_channels(struct mmc_davinci_host *host) |
| 593 | { | 508 | { |
| 594 | unsigned i; | ||
| 595 | |||
| 596 | if (!host->use_dma) | 509 | if (!host->use_dma) |
| 597 | return; | 510 | return; |
| 598 | 511 | ||
| 599 | for (i = 0; i < host->n_link; i++) | 512 | dma_release_channel(host->dma_tx); |
| 600 | edma_free_slot(host->links[i]); | 513 | dma_release_channel(host->dma_rx); |
| 601 | |||
| 602 | edma_free_channel(host->txdma); | ||
| 603 | edma_free_channel(host->rxdma); | ||
| 604 | } | 514 | } |
| 605 | 515 | ||
| 606 | static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host) | 516 | static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host) |
| 607 | { | 517 | { |
| 608 | u32 link_size; | 518 | int r; |
| 609 | int r, i; | 519 | dma_cap_mask_t mask; |
| 610 | 520 | ||
| 611 | /* Acquire master DMA write channel */ | 521 | dma_cap_zero(mask); |
| 612 | r = edma_alloc_channel(host->txdma, mmc_davinci_dma_cb, host, | 522 | dma_cap_set(DMA_SLAVE, mask); |
| 613 | EVENTQ_DEFAULT); | 523 | |
| 614 | if (r < 0) { | 524 | host->dma_tx = |
| 615 | dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n", | 525 | dma_request_channel(mask, edma_filter_fn, &host->txdma); |
| 616 | "tx", r); | 526 | if (!host->dma_tx) { |
| 617 | return r; | 527 | dev_err(mmc_dev(host->mmc), "Can't get dma_tx channel\n"); |
| 618 | } | 528 | return -ENODEV; |
| 619 | mmc_davinci_dma_setup(host, true, &host->tx_template); | ||
| 620 | |||
| 621 | /* Acquire master DMA read channel */ | ||
| 622 | r = edma_alloc_channel(host->rxdma, mmc_davinci_dma_cb, host, | ||
| 623 | EVENTQ_DEFAULT); | ||
| 624 | if (r < 0) { | ||
| 625 | dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n", | ||
| 626 | "rx", r); | ||
| 627 | goto free_master_write; | ||
| 628 | } | 529 | } |
| 629 | mmc_davinci_dma_setup(host, false, &host->rx_template); | ||
| 630 | 530 | ||
| 631 | /* Allocate parameter RAM slots, which will later be bound to a | 531 | host->dma_rx = |
| 632 | * channel as needed to handle a scatterlist. | 532 | dma_request_channel(mask, edma_filter_fn, &host->rxdma); |
| 633 | */ | 533 | if (!host->dma_rx) { |
| 634 | link_size = min_t(unsigned, host->nr_sg, ARRAY_SIZE(host->links)); | 534 | dev_err(mmc_dev(host->mmc), "Can't get dma_rx channel\n"); |
| 635 | for (i = 0; i < link_size; i++) { | 535 | r = -ENODEV; |
| 636 | r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY); | 536 | goto free_master_write; |
| 637 | if (r < 0) { | ||
| 638 | dev_dbg(mmc_dev(host->mmc), "dma PaRAM alloc --> %d\n", | ||
| 639 | r); | ||
| 640 | break; | ||
| 641 | } | ||
| 642 | host->links[i] = r; | ||
| 643 | } | 537 | } |
| 644 | host->n_link = i; | ||
| 645 | 538 | ||
| 646 | return 0; | 539 | return 0; |
| 647 | 540 | ||
| 648 | free_master_write: | 541 | free_master_write: |
| 649 | edma_free_channel(host->txdma); | 542 | dma_release_channel(host->dma_tx); |
| 650 | 543 | ||
| 651 | return r; | 544 | return r; |
| 652 | } | 545 | } |
| @@ -1359,7 +1252,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) | |||
| 1359 | * Each hw_seg uses one EDMA parameter RAM slot, always one | 1252 | * Each hw_seg uses one EDMA parameter RAM slot, always one |
| 1360 | * channel and then usually some linked slots. | 1253 | * channel and then usually some linked slots. |
| 1361 | */ | 1254 | */ |
| 1362 | mmc->max_segs = 1 + host->n_link; | 1255 | mmc->max_segs = MAX_NR_SG; |
| 1363 | 1256 | ||
| 1364 | /* EDMA limit per hw segment (one or two MBytes) */ | 1257 | /* EDMA limit per hw segment (one or two MBytes) */ |
| 1365 | mmc->max_seg_size = MAX_CCNT * rw_threshold; | 1258 | mmc->max_seg_size = MAX_CCNT * rw_threshold; |
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c new file mode 100644 index 000000000000..660bbc528862 --- /dev/null +++ b/drivers/mmc/host/dw_mmc-exynos.c | |||
| @@ -0,0 +1,253 @@ | |||
| 1 | /* | ||
| 2 | * Exynos Specific Extensions for Synopsys DW Multimedia Card Interface driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012, Samsung Electronics Co., Ltd. | ||
| 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 as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <linux/clk.h> | ||
| 15 | #include <linux/mmc/host.h> | ||
| 16 | #include <linux/mmc/dw_mmc.h> | ||
| 17 | #include <linux/of.h> | ||
| 18 | #include <linux/of_gpio.h> | ||
| 19 | |||
| 20 | #include "dw_mmc.h" | ||
| 21 | #include "dw_mmc-pltfm.h" | ||
| 22 | |||
| 23 | #define NUM_PINS(x) (x + 2) | ||
| 24 | |||
| 25 | #define SDMMC_CLKSEL 0x09C | ||
| 26 | #define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0) | ||
| 27 | #define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16) | ||
| 28 | #define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24) | ||
| 29 | #define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7) | ||
| 30 | #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ | ||
| 31 | SDMMC_CLKSEL_CCLK_DRIVE(y) | \ | ||
| 32 | SDMMC_CLKSEL_CCLK_DIVIDER(z)) | ||
| 33 | |||
| 34 | #define SDMMC_CMD_USE_HOLD_REG BIT(29) | ||
| 35 | |||
| 36 | #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 | ||
| 37 | #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 | ||
| 38 | |||
| 39 | /* Variations in Exynos specific dw-mshc controller */ | ||
| 40 | enum dw_mci_exynos_type { | ||
| 41 | DW_MCI_TYPE_EXYNOS4210, | ||
| 42 | DW_MCI_TYPE_EXYNOS4412, | ||
| 43 | DW_MCI_TYPE_EXYNOS5250, | ||
| 44 | }; | ||
| 45 | |||
| 46 | /* Exynos implementation specific driver private data */ | ||
| 47 | struct dw_mci_exynos_priv_data { | ||
| 48 | enum dw_mci_exynos_type ctrl_type; | ||
| 49 | u8 ciu_div; | ||
| 50 | u32 sdr_timing; | ||
| 51 | u32 ddr_timing; | ||
| 52 | }; | ||
| 53 | |||
| 54 | static struct dw_mci_exynos_compatible { | ||
| 55 | char *compatible; | ||
| 56 | enum dw_mci_exynos_type ctrl_type; | ||
| 57 | } exynos_compat[] = { | ||
| 58 | { | ||
| 59 | .compatible = "samsung,exynos4210-dw-mshc", | ||
| 60 | .ctrl_type = DW_MCI_TYPE_EXYNOS4210, | ||
| 61 | }, { | ||
| 62 | .compatible = "samsung,exynos4412-dw-mshc", | ||
| 63 | .ctrl_type = DW_MCI_TYPE_EXYNOS4412, | ||
| 64 | }, { | ||
| 65 | .compatible = "samsung,exynos5250-dw-mshc", | ||
| 66 | .ctrl_type = DW_MCI_TYPE_EXYNOS5250, | ||
| 67 | }, | ||
| 68 | }; | ||
| 69 | |||
| 70 | static int dw_mci_exynos_priv_init(struct dw_mci *host) | ||
| 71 | { | ||
| 72 | struct dw_mci_exynos_priv_data *priv; | ||
| 73 | int idx; | ||
| 74 | |||
| 75 | priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); | ||
| 76 | if (!priv) { | ||
| 77 | dev_err(host->dev, "mem alloc failed for private data\n"); | ||
| 78 | return -ENOMEM; | ||
| 79 | } | ||
| 80 | |||
| 81 | for (idx = 0; idx < ARRAY_SIZE(exynos_compat); idx++) { | ||
| 82 | if (of_device_is_compatible(host->dev->of_node, | ||
| 83 | exynos_compat[idx].compatible)) | ||
| 84 | priv->ctrl_type = exynos_compat[idx].ctrl_type; | ||
| 85 | } | ||
| 86 | |||
| 87 | host->priv = priv; | ||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | |||
| 91 | static int dw_mci_exynos_setup_clock(struct dw_mci *host) | ||
| 92 | { | ||
| 93 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
| 94 | |||
| 95 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250) | ||
| 96 | host->bus_hz /= (priv->ciu_div + 1); | ||
| 97 | else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412) | ||
| 98 | host->bus_hz /= EXYNOS4412_FIXED_CIU_CLK_DIV; | ||
| 99 | else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210) | ||
| 100 | host->bus_hz /= EXYNOS4210_FIXED_CIU_CLK_DIV; | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) | ||
| 106 | { | ||
| 107 | /* | ||
| 108 | * Exynos4412 and Exynos5250 extends the use of CMD register with the | ||
| 109 | * use of bit 29 (which is reserved on standard MSHC controllers) for | ||
| 110 | * optionally bypassing the HOLD register for command and data. The | ||
| 111 | * HOLD register should be bypassed in case there is no phase shift | ||
| 112 | * applied on CMD/DATA that is sent to the card. | ||
| 113 | */ | ||
| 114 | if (SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL))) | ||
| 115 | *cmdr |= SDMMC_CMD_USE_HOLD_REG; | ||
| 116 | } | ||
| 117 | |||
| 118 | static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) | ||
| 119 | { | ||
| 120 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
| 121 | |||
| 122 | if (ios->timing == MMC_TIMING_UHS_DDR50) | ||
| 123 | mci_writel(host, CLKSEL, priv->ddr_timing); | ||
| 124 | else | ||
| 125 | mci_writel(host, CLKSEL, priv->sdr_timing); | ||
| 126 | } | ||
| 127 | |||
| 128 | static int dw_mci_exynos_parse_dt(struct dw_mci *host) | ||
| 129 | { | ||
| 130 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
| 131 | struct device_node *np = host->dev->of_node; | ||
| 132 | u32 timing[2]; | ||
| 133 | u32 div = 0; | ||
| 134 | int ret; | ||
| 135 | |||
| 136 | of_property_read_u32(np, "samsung,dw-mshc-ciu-div", &div); | ||
| 137 | priv->ciu_div = div; | ||
| 138 | |||
| 139 | ret = of_property_read_u32_array(np, | ||
| 140 | "samsung,dw-mshc-sdr-timing", timing, 2); | ||
| 141 | if (ret) | ||
| 142 | return ret; | ||
| 143 | |||
| 144 | priv->sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); | ||
| 145 | |||
| 146 | ret = of_property_read_u32_array(np, | ||
| 147 | "samsung,dw-mshc-ddr-timing", timing, 2); | ||
| 148 | if (ret) | ||
| 149 | return ret; | ||
| 150 | |||
| 151 | priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); | ||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | static int dw_mci_exynos_setup_bus(struct dw_mci *host, | ||
| 156 | struct device_node *slot_np, u8 bus_width) | ||
| 157 | { | ||
| 158 | int idx, gpio, ret; | ||
| 159 | |||
| 160 | if (!slot_np) | ||
| 161 | return -EINVAL; | ||
| 162 | |||
| 163 | /* cmd + clock + bus-width pins */ | ||
| 164 | for (idx = 0; idx < NUM_PINS(bus_width); idx++) { | ||
| 165 | gpio = of_get_gpio(slot_np, idx); | ||
| 166 | if (!gpio_is_valid(gpio)) { | ||
| 167 | dev_err(host->dev, "invalid gpio: %d\n", gpio); | ||
| 168 | return -EINVAL; | ||
| 169 | } | ||
| 170 | |||
| 171 | ret = devm_gpio_request(host->dev, gpio, "dw-mci-bus"); | ||
| 172 | if (ret) { | ||
| 173 | dev_err(host->dev, "gpio [%d] request failed\n", gpio); | ||
| 174 | return -EBUSY; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | gpio = of_get_named_gpio(slot_np, "wp-gpios", 0); | ||
| 179 | if (gpio_is_valid(gpio)) { | ||
| 180 | if (devm_gpio_request(host->dev, gpio, "dw-mci-wp")) | ||
| 181 | dev_info(host->dev, "gpio [%d] request failed\n", | ||
| 182 | gpio); | ||
| 183 | } else { | ||
| 184 | dev_info(host->dev, "wp gpio not available"); | ||
| 185 | host->pdata->quirks |= DW_MCI_QUIRK_NO_WRITE_PROTECT; | ||
| 186 | } | ||
| 187 | |||
| 188 | if (host->pdata->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) | ||
| 189 | return 0; | ||
| 190 | |||
| 191 | gpio = of_get_named_gpio(slot_np, "samsung,cd-pinmux-gpio", 0); | ||
| 192 | if (gpio_is_valid(gpio)) { | ||
| 193 | if (devm_gpio_request(host->dev, gpio, "dw-mci-cd")) | ||
| 194 | dev_err(host->dev, "gpio [%d] request failed\n", gpio); | ||
| 195 | } else { | ||
| 196 | dev_info(host->dev, "cd gpio not available"); | ||
| 197 | } | ||
| 198 | |||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | |||
| 202 | /* Exynos5250 controller specific capabilities */ | ||
| 203 | static unsigned long exynos5250_dwmmc_caps[4] = { | ||
| 204 | MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | | ||
| 205 | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, | ||
| 206 | MMC_CAP_CMD23, | ||
| 207 | MMC_CAP_CMD23, | ||
| 208 | MMC_CAP_CMD23, | ||
| 209 | }; | ||
| 210 | |||
| 211 | static struct dw_mci_drv_data exynos5250_drv_data = { | ||
| 212 | .caps = exynos5250_dwmmc_caps, | ||
| 213 | .init = dw_mci_exynos_priv_init, | ||
| 214 | .setup_clock = dw_mci_exynos_setup_clock, | ||
| 215 | .prepare_command = dw_mci_exynos_prepare_command, | ||
| 216 | .set_ios = dw_mci_exynos_set_ios, | ||
| 217 | .parse_dt = dw_mci_exynos_parse_dt, | ||
| 218 | .setup_bus = dw_mci_exynos_setup_bus, | ||
| 219 | }; | ||
| 220 | |||
| 221 | static const struct of_device_id dw_mci_exynos_match[] = { | ||
| 222 | { .compatible = "samsung,exynos5250-dw-mshc", | ||
| 223 | .data = (void *)&exynos5250_drv_data, }, | ||
| 224 | {}, | ||
| 225 | }; | ||
| 226 | MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); | ||
| 227 | |||
| 228 | int dw_mci_exynos_probe(struct platform_device *pdev) | ||
| 229 | { | ||
| 230 | struct dw_mci_drv_data *drv_data; | ||
| 231 | const struct of_device_id *match; | ||
| 232 | |||
| 233 | match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node); | ||
| 234 | drv_data = match->data; | ||
| 235 | return dw_mci_pltfm_register(pdev, drv_data); | ||
| 236 | } | ||
| 237 | |||
| 238 | static struct platform_driver dw_mci_exynos_pltfm_driver = { | ||
| 239 | .probe = dw_mci_exynos_probe, | ||
| 240 | .remove = __exit_p(dw_mci_pltfm_remove), | ||
| 241 | .driver = { | ||
| 242 | .name = "dwmmc_exynos", | ||
| 243 | .of_match_table = of_match_ptr(dw_mci_exynos_match), | ||
| 244 | .pm = &dw_mci_pltfm_pmops, | ||
| 245 | }, | ||
| 246 | }; | ||
| 247 | |||
| 248 | module_platform_driver(dw_mci_exynos_pltfm_driver); | ||
| 249 | |||
| 250 | MODULE_DESCRIPTION("Samsung Specific DW-MSHC Driver Extension"); | ||
| 251 | MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com"); | ||
| 252 | MODULE_LICENSE("GPL v2"); | ||
| 253 | MODULE_ALIAS("platform:dwmmc-exynos"); | ||
diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c index dc0d25a013e0..edb37e9135ae 100644 --- a/drivers/mmc/host/dw_mmc-pci.c +++ b/drivers/mmc/host/dw_mmc-pci.c | |||
| @@ -59,7 +59,7 @@ static int __devinit dw_mci_pci_probe(struct pci_dev *pdev, | |||
| 59 | 59 | ||
| 60 | host->irq = pdev->irq; | 60 | host->irq = pdev->irq; |
| 61 | host->irq_flags = IRQF_SHARED; | 61 | host->irq_flags = IRQF_SHARED; |
| 62 | host->dev = pdev->dev; | 62 | host->dev = &pdev->dev; |
| 63 | host->pdata = &pci_board_data; | 63 | host->pdata = &pci_board_data; |
| 64 | 64 | ||
| 65 | host->regs = pci_iomap(pdev, PCI_BAR_NO, COMPLETE_BAR); | 65 | host->regs = pci_iomap(pdev, PCI_BAR_NO, COMPLETE_BAR); |
| @@ -140,18 +140,7 @@ static struct pci_driver dw_mci_pci_driver = { | |||
| 140 | }, | 140 | }, |
| 141 | }; | 141 | }; |
| 142 | 142 | ||
| 143 | static int __init dw_mci_init(void) | 143 | module_pci_driver(dw_mci_pci_driver); |
| 144 | { | ||
| 145 | return pci_register_driver(&dw_mci_pci_driver); | ||
| 146 | } | ||
| 147 | |||
| 148 | static void __exit dw_mci_exit(void) | ||
| 149 | { | ||
| 150 | pci_unregister_driver(&dw_mci_pci_driver); | ||
| 151 | } | ||
| 152 | |||
| 153 | module_init(dw_mci_init); | ||
| 154 | module_exit(dw_mci_exit); | ||
| 155 | 144 | ||
| 156 | MODULE_DESCRIPTION("DW Multimedia Card PCI Interface driver"); | 145 | MODULE_DESCRIPTION("DW Multimedia Card PCI Interface driver"); |
| 157 | MODULE_AUTHOR("Shashidhar Hiremath <shashidharh@vayavyalabs.com>"); | 146 | MODULE_AUTHOR("Shashidhar Hiremath <shashidharh@vayavyalabs.com>"); |
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 92ec3eb3aae7..c960ca7ffbe6 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c | |||
| @@ -19,59 +19,63 @@ | |||
| 19 | #include <linux/mmc/host.h> | 19 | #include <linux/mmc/host.h> |
| 20 | #include <linux/mmc/mmc.h> | 20 | #include <linux/mmc/mmc.h> |
| 21 | #include <linux/mmc/dw_mmc.h> | 21 | #include <linux/mmc/dw_mmc.h> |
| 22 | #include <linux/of.h> | ||
| 23 | |||
| 22 | #include "dw_mmc.h" | 24 | #include "dw_mmc.h" |
| 23 | 25 | ||
| 24 | static int dw_mci_pltfm_probe(struct platform_device *pdev) | 26 | int dw_mci_pltfm_register(struct platform_device *pdev, |
| 27 | struct dw_mci_drv_data *drv_data) | ||
| 25 | { | 28 | { |
| 26 | struct dw_mci *host; | 29 | struct dw_mci *host; |
| 27 | struct resource *regs; | 30 | struct resource *regs; |
| 28 | int ret; | 31 | int ret; |
| 29 | 32 | ||
| 30 | host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL); | 33 | host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL); |
| 31 | if (!host) | 34 | if (!host) |
| 32 | return -ENOMEM; | 35 | return -ENOMEM; |
| 33 | 36 | ||
| 34 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 37 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 35 | if (!regs) { | 38 | if (!regs) |
| 36 | ret = -ENXIO; | 39 | return -ENXIO; |
| 37 | goto err_free; | ||
| 38 | } | ||
| 39 | 40 | ||
| 40 | host->irq = platform_get_irq(pdev, 0); | 41 | host->irq = platform_get_irq(pdev, 0); |
| 41 | if (host->irq < 0) { | 42 | if (host->irq < 0) |
| 42 | ret = host->irq; | 43 | return host->irq; |
| 43 | goto err_free; | ||
| 44 | } | ||
| 45 | 44 | ||
| 46 | host->dev = pdev->dev; | 45 | host->drv_data = drv_data; |
| 46 | host->dev = &pdev->dev; | ||
| 47 | host->irq_flags = 0; | 47 | host->irq_flags = 0; |
| 48 | host->pdata = pdev->dev.platform_data; | 48 | host->pdata = pdev->dev.platform_data; |
| 49 | ret = -ENOMEM; | 49 | host->regs = devm_request_and_ioremap(&pdev->dev, regs); |
| 50 | host->regs = ioremap(regs->start, resource_size(regs)); | ||
| 51 | if (!host->regs) | 50 | if (!host->regs) |
| 52 | goto err_free; | 51 | return -ENOMEM; |
| 52 | |||
| 53 | if (host->drv_data->init) { | ||
| 54 | ret = host->drv_data->init(host); | ||
| 55 | if (ret) | ||
| 56 | return ret; | ||
| 57 | } | ||
| 58 | |||
| 53 | platform_set_drvdata(pdev, host); | 59 | platform_set_drvdata(pdev, host); |
| 54 | ret = dw_mci_probe(host); | 60 | ret = dw_mci_probe(host); |
| 55 | if (ret) | ||
| 56 | goto err_out; | ||
| 57 | return ret; | ||
| 58 | err_out: | ||
| 59 | iounmap(host->regs); | ||
| 60 | err_free: | ||
| 61 | kfree(host); | ||
| 62 | return ret; | 61 | return ret; |
| 63 | } | 62 | } |
| 63 | EXPORT_SYMBOL_GPL(dw_mci_pltfm_register); | ||
| 64 | 64 | ||
| 65 | static int __exit dw_mci_pltfm_remove(struct platform_device *pdev) | 65 | static int __devinit dw_mci_pltfm_probe(struct platform_device *pdev) |
| 66 | { | ||
| 67 | return dw_mci_pltfm_register(pdev, NULL); | ||
| 68 | } | ||
| 69 | |||
| 70 | static int __devexit dw_mci_pltfm_remove(struct platform_device *pdev) | ||
| 66 | { | 71 | { |
| 67 | struct dw_mci *host = platform_get_drvdata(pdev); | 72 | struct dw_mci *host = platform_get_drvdata(pdev); |
| 68 | 73 | ||
| 69 | platform_set_drvdata(pdev, NULL); | 74 | platform_set_drvdata(pdev, NULL); |
| 70 | dw_mci_remove(host); | 75 | dw_mci_remove(host); |
| 71 | iounmap(host->regs); | ||
| 72 | kfree(host); | ||
| 73 | return 0; | 76 | return 0; |
| 74 | } | 77 | } |
| 78 | EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove); | ||
| 75 | 79 | ||
| 76 | #ifdef CONFIG_PM_SLEEP | 80 | #ifdef CONFIG_PM_SLEEP |
| 77 | /* | 81 | /* |
| @@ -105,12 +109,20 @@ static int dw_mci_pltfm_resume(struct device *dev) | |||
| 105 | #define dw_mci_pltfm_resume NULL | 109 | #define dw_mci_pltfm_resume NULL |
| 106 | #endif /* CONFIG_PM_SLEEP */ | 110 | #endif /* CONFIG_PM_SLEEP */ |
| 107 | 111 | ||
| 108 | static SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume); | 112 | SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume); |
| 113 | EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops); | ||
| 114 | |||
| 115 | static const struct of_device_id dw_mci_pltfm_match[] = { | ||
| 116 | { .compatible = "snps,dw-mshc", }, | ||
| 117 | {}, | ||
| 118 | }; | ||
| 119 | MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); | ||
| 109 | 120 | ||
| 110 | static struct platform_driver dw_mci_pltfm_driver = { | 121 | static struct platform_driver dw_mci_pltfm_driver = { |
| 111 | .remove = __exit_p(dw_mci_pltfm_remove), | 122 | .remove = __exit_p(dw_mci_pltfm_remove), |
| 112 | .driver = { | 123 | .driver = { |
| 113 | .name = "dw_mmc", | 124 | .name = "dw_mmc", |
| 125 | .of_match_table = of_match_ptr(dw_mci_pltfm_match), | ||
| 114 | .pm = &dw_mci_pltfm_pmops, | 126 | .pm = &dw_mci_pltfm_pmops, |
| 115 | }, | 127 | }, |
| 116 | }; | 128 | }; |
diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h new file mode 100644 index 000000000000..301f24541fc2 --- /dev/null +++ b/drivers/mmc/host/dw_mmc-pltfm.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | /* | ||
| 2 | * Synopsys DesignWare Multimedia Card Interface Platform driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012, Samsung Electronics Co., Ltd. | ||
| 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 as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef _DW_MMC_PLTFM_H_ | ||
| 13 | #define _DW_MMC_PLTFM_H_ | ||
| 14 | |||
| 15 | extern int dw_mci_pltfm_register(struct platform_device *pdev, | ||
| 16 | struct dw_mci_drv_data *drv_data); | ||
| 17 | extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev); | ||
| 18 | extern const struct dev_pm_ops dw_mci_pltfm_pmops; | ||
| 19 | |||
| 20 | #endif /* _DW_MMC_PLTFM_H_ */ | ||
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index af40d227bece..c2828f35c3b8 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/bitops.h> | 33 | #include <linux/bitops.h> |
| 34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
| 35 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
| 36 | #include <linux/of.h> | ||
| 36 | 37 | ||
| 37 | #include "dw_mmc.h" | 38 | #include "dw_mmc.h" |
| 38 | 39 | ||
| @@ -230,6 +231,7 @@ static void dw_mci_set_timeout(struct dw_mci *host) | |||
| 230 | static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) | 231 | static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) |
| 231 | { | 232 | { |
| 232 | struct mmc_data *data; | 233 | struct mmc_data *data; |
| 234 | struct dw_mci_slot *slot = mmc_priv(mmc); | ||
| 233 | u32 cmdr; | 235 | u32 cmdr; |
| 234 | cmd->error = -EINPROGRESS; | 236 | cmd->error = -EINPROGRESS; |
| 235 | 237 | ||
| @@ -259,6 +261,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) | |||
| 259 | cmdr |= SDMMC_CMD_DAT_WR; | 261 | cmdr |= SDMMC_CMD_DAT_WR; |
| 260 | } | 262 | } |
| 261 | 263 | ||
| 264 | if (slot->host->drv_data->prepare_command) | ||
| 265 | slot->host->drv_data->prepare_command(slot->host, &cmdr); | ||
| 266 | |||
| 262 | return cmdr; | 267 | return cmdr; |
| 263 | } | 268 | } |
| 264 | 269 | ||
| @@ -266,7 +271,7 @@ static void dw_mci_start_command(struct dw_mci *host, | |||
| 266 | struct mmc_command *cmd, u32 cmd_flags) | 271 | struct mmc_command *cmd, u32 cmd_flags) |
| 267 | { | 272 | { |
| 268 | host->cmd = cmd; | 273 | host->cmd = cmd; |
| 269 | dev_vdbg(&host->dev, | 274 | dev_vdbg(host->dev, |
| 270 | "start command: ARGR=0x%08x CMDR=0x%08x\n", | 275 | "start command: ARGR=0x%08x CMDR=0x%08x\n", |
| 271 | cmd->arg, cmd_flags); | 276 | cmd->arg, cmd_flags); |
| 272 | 277 | ||
| @@ -308,7 +313,7 @@ static void dw_mci_dma_cleanup(struct dw_mci *host) | |||
| 308 | 313 | ||
| 309 | if (data) | 314 | if (data) |
| 310 | if (!data->host_cookie) | 315 | if (!data->host_cookie) |
| 311 | dma_unmap_sg(&host->dev, | 316 | dma_unmap_sg(host->dev, |
| 312 | data->sg, | 317 | data->sg, |
| 313 | data->sg_len, | 318 | data->sg_len, |
| 314 | dw_mci_get_dma_dir(data)); | 319 | dw_mci_get_dma_dir(data)); |
| @@ -334,7 +339,7 @@ static void dw_mci_idmac_complete_dma(struct dw_mci *host) | |||
| 334 | { | 339 | { |
| 335 | struct mmc_data *data = host->data; | 340 | struct mmc_data *data = host->data; |
| 336 | 341 | ||
| 337 | dev_vdbg(&host->dev, "DMA complete\n"); | 342 | dev_vdbg(host->dev, "DMA complete\n"); |
| 338 | 343 | ||
| 339 | host->dma_ops->cleanup(host); | 344 | host->dma_ops->cleanup(host); |
| 340 | 345 | ||
| @@ -405,23 +410,11 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) | |||
| 405 | static int dw_mci_idmac_init(struct dw_mci *host) | 410 | static int dw_mci_idmac_init(struct dw_mci *host) |
| 406 | { | 411 | { |
| 407 | struct idmac_desc *p; | 412 | struct idmac_desc *p; |
| 408 | int i, dma_support; | 413 | int i; |
| 409 | 414 | ||
| 410 | /* Number of descriptors in the ring buffer */ | 415 | /* Number of descriptors in the ring buffer */ |
| 411 | host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); | 416 | host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); |
| 412 | 417 | ||
| 413 | /* Check if Hardware Configuration Register has support for DMA */ | ||
| 414 | dma_support = (mci_readl(host, HCON) >> 16) & 0x3; | ||
| 415 | |||
| 416 | if (!dma_support || dma_support > 2) { | ||
| 417 | dev_err(&host->dev, | ||
| 418 | "Host Controller does not support IDMA Tx.\n"); | ||
| 419 | host->dma_ops = NULL; | ||
| 420 | return -ENODEV; | ||
| 421 | } | ||
| 422 | |||
| 423 | dev_info(&host->dev, "Using internal DMA controller.\n"); | ||
| 424 | |||
| 425 | /* Forward link the descriptor list */ | 418 | /* Forward link the descriptor list */ |
| 426 | for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) | 419 | for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) |
| 427 | p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1)); | 420 | p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1)); |
| @@ -476,7 +469,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host, | |||
| 476 | return -EINVAL; | 469 | return -EINVAL; |
| 477 | } | 470 | } |
| 478 | 471 | ||
| 479 | sg_len = dma_map_sg(&host->dev, | 472 | sg_len = dma_map_sg(host->dev, |
| 480 | data->sg, | 473 | data->sg, |
| 481 | data->sg_len, | 474 | data->sg_len, |
| 482 | dw_mci_get_dma_dir(data)); | 475 | dw_mci_get_dma_dir(data)); |
| @@ -519,7 +512,7 @@ static void dw_mci_post_req(struct mmc_host *mmc, | |||
| 519 | return; | 512 | return; |
| 520 | 513 | ||
| 521 | if (data->host_cookie) | 514 | if (data->host_cookie) |
| 522 | dma_unmap_sg(&slot->host->dev, | 515 | dma_unmap_sg(slot->host->dev, |
| 523 | data->sg, | 516 | data->sg, |
| 524 | data->sg_len, | 517 | data->sg_len, |
| 525 | dw_mci_get_dma_dir(data)); | 518 | dw_mci_get_dma_dir(data)); |
| @@ -545,7 +538,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) | |||
| 545 | 538 | ||
| 546 | host->using_dma = 1; | 539 | host->using_dma = 1; |
| 547 | 540 | ||
| 548 | dev_vdbg(&host->dev, | 541 | dev_vdbg(host->dev, |
| 549 | "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n", | 542 | "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n", |
| 550 | (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, | 543 | (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, |
| 551 | sg_len); | 544 | sg_len); |
| @@ -814,6 +807,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 814 | slot->clock = ios->clock; | 807 | slot->clock = ios->clock; |
| 815 | } | 808 | } |
| 816 | 809 | ||
| 810 | if (slot->host->drv_data->set_ios) | ||
| 811 | slot->host->drv_data->set_ios(slot->host, ios); | ||
| 812 | |||
| 817 | switch (ios->power_mode) { | 813 | switch (ios->power_mode) { |
| 818 | case MMC_POWER_UP: | 814 | case MMC_POWER_UP: |
| 819 | set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); | 815 | set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); |
| @@ -830,7 +826,9 @@ static int dw_mci_get_ro(struct mmc_host *mmc) | |||
| 830 | struct dw_mci_board *brd = slot->host->pdata; | 826 | struct dw_mci_board *brd = slot->host->pdata; |
| 831 | 827 | ||
| 832 | /* Use platform get_ro function, else try on board write protect */ | 828 | /* Use platform get_ro function, else try on board write protect */ |
| 833 | if (brd->get_ro) | 829 | if (brd->quirks & DW_MCI_QUIRK_NO_WRITE_PROTECT) |
| 830 | read_only = 0; | ||
| 831 | else if (brd->get_ro) | ||
| 834 | read_only = brd->get_ro(slot->id); | 832 | read_only = brd->get_ro(slot->id); |
| 835 | else | 833 | else |
| 836 | read_only = | 834 | read_only = |
| @@ -939,12 +937,12 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) | |||
| 939 | slot = list_entry(host->queue.next, | 937 | slot = list_entry(host->queue.next, |
| 940 | struct dw_mci_slot, queue_node); | 938 | struct dw_mci_slot, queue_node); |
| 941 | list_del(&slot->queue_node); | 939 | list_del(&slot->queue_node); |
| 942 | dev_vdbg(&host->dev, "list not empty: %s is next\n", | 940 | dev_vdbg(host->dev, "list not empty: %s is next\n", |
| 943 | mmc_hostname(slot->mmc)); | 941 | mmc_hostname(slot->mmc)); |
| 944 | host->state = STATE_SENDING_CMD; | 942 | host->state = STATE_SENDING_CMD; |
| 945 | dw_mci_start_request(host, slot); | 943 | dw_mci_start_request(host, slot); |
| 946 | } else { | 944 | } else { |
| 947 | dev_vdbg(&host->dev, "list empty\n"); | 945 | dev_vdbg(host->dev, "list empty\n"); |
| 948 | host->state = STATE_IDLE; | 946 | host->state = STATE_IDLE; |
| 949 | } | 947 | } |
| 950 | 948 | ||
| @@ -1083,7 +1081,7 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
| 1083 | data->bytes_xfered = 0; | 1081 | data->bytes_xfered = 0; |
| 1084 | data->error = -ETIMEDOUT; | 1082 | data->error = -ETIMEDOUT; |
| 1085 | } else { | 1083 | } else { |
| 1086 | dev_err(&host->dev, | 1084 | dev_err(host->dev, |
| 1087 | "data FIFO error " | 1085 | "data FIFO error " |
| 1088 | "(status=%08x)\n", | 1086 | "(status=%08x)\n", |
| 1089 | status); | 1087 | status); |
| @@ -1767,12 +1765,60 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
| 1767 | } | 1765 | } |
| 1768 | } | 1766 | } |
| 1769 | 1767 | ||
| 1770 | static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | 1768 | #ifdef CONFIG_OF |
| 1769 | /* given a slot id, find out the device node representing that slot */ | ||
| 1770 | static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) | ||
| 1771 | { | ||
| 1772 | struct device_node *np; | ||
| 1773 | const __be32 *addr; | ||
| 1774 | int len; | ||
| 1775 | |||
| 1776 | if (!dev || !dev->of_node) | ||
| 1777 | return NULL; | ||
| 1778 | |||
| 1779 | for_each_child_of_node(dev->of_node, np) { | ||
| 1780 | addr = of_get_property(np, "reg", &len); | ||
| 1781 | if (!addr || (len < sizeof(int))) | ||
| 1782 | continue; | ||
| 1783 | if (be32_to_cpup(addr) == slot) | ||
| 1784 | return np; | ||
| 1785 | } | ||
| 1786 | return NULL; | ||
| 1787 | } | ||
| 1788 | |||
| 1789 | /* find out bus-width for a given slot */ | ||
| 1790 | static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) | ||
| 1791 | { | ||
| 1792 | struct device_node *np = dw_mci_of_find_slot_node(dev, slot); | ||
| 1793 | u32 bus_wd = 1; | ||
| 1794 | |||
| 1795 | if (!np) | ||
| 1796 | return 1; | ||
| 1797 | |||
| 1798 | if (of_property_read_u32(np, "bus-width", &bus_wd)) | ||
| 1799 | dev_err(dev, "bus-width property not found, assuming width" | ||
| 1800 | " as 1\n"); | ||
| 1801 | return bus_wd; | ||
| 1802 | } | ||
| 1803 | #else /* CONFIG_OF */ | ||
| 1804 | static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) | ||
| 1805 | { | ||
| 1806 | return 1; | ||
| 1807 | } | ||
| 1808 | static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) | ||
| 1809 | { | ||
| 1810 | return NULL; | ||
| 1811 | } | ||
| 1812 | #endif /* CONFIG_OF */ | ||
| 1813 | |||
| 1814 | static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | ||
| 1771 | { | 1815 | { |
| 1772 | struct mmc_host *mmc; | 1816 | struct mmc_host *mmc; |
| 1773 | struct dw_mci_slot *slot; | 1817 | struct dw_mci_slot *slot; |
| 1818 | int ctrl_id, ret; | ||
| 1819 | u8 bus_width; | ||
| 1774 | 1820 | ||
| 1775 | mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), &host->dev); | 1821 | mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); |
| 1776 | if (!mmc) | 1822 | if (!mmc) |
| 1777 | return -ENOMEM; | 1823 | return -ENOMEM; |
| 1778 | 1824 | ||
| @@ -1780,6 +1826,7 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
| 1780 | slot->id = id; | 1826 | slot->id = id; |
| 1781 | slot->mmc = mmc; | 1827 | slot->mmc = mmc; |
| 1782 | slot->host = host; | 1828 | slot->host = host; |
| 1829 | host->slot[id] = slot; | ||
| 1783 | 1830 | ||
| 1784 | mmc->ops = &dw_mci_ops; | 1831 | mmc->ops = &dw_mci_ops; |
| 1785 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510); | 1832 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510); |
| @@ -1800,21 +1847,44 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
| 1800 | if (host->pdata->caps) | 1847 | if (host->pdata->caps) |
| 1801 | mmc->caps = host->pdata->caps; | 1848 | mmc->caps = host->pdata->caps; |
| 1802 | 1849 | ||
| 1850 | if (host->dev->of_node) { | ||
| 1851 | ctrl_id = of_alias_get_id(host->dev->of_node, "mshc"); | ||
| 1852 | if (ctrl_id < 0) | ||
| 1853 | ctrl_id = 0; | ||
| 1854 | } else { | ||
| 1855 | ctrl_id = to_platform_device(host->dev)->id; | ||
| 1856 | } | ||
| 1857 | if (host->drv_data && host->drv_data->caps) | ||
| 1858 | mmc->caps |= host->drv_data->caps[ctrl_id]; | ||
| 1859 | |||
| 1803 | if (host->pdata->caps2) | 1860 | if (host->pdata->caps2) |
| 1804 | mmc->caps2 = host->pdata->caps2; | 1861 | mmc->caps2 = host->pdata->caps2; |
| 1805 | 1862 | ||
| 1806 | if (host->pdata->get_bus_wd) | 1863 | if (host->pdata->get_bus_wd) |
| 1807 | if (host->pdata->get_bus_wd(slot->id) >= 4) | 1864 | bus_width = host->pdata->get_bus_wd(slot->id); |
| 1808 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1865 | else if (host->dev->of_node) |
| 1866 | bus_width = dw_mci_of_get_bus_wd(host->dev, slot->id); | ||
| 1867 | else | ||
| 1868 | bus_width = 1; | ||
| 1869 | |||
| 1870 | if (host->drv_data->setup_bus) { | ||
| 1871 | struct device_node *slot_np; | ||
| 1872 | slot_np = dw_mci_of_find_slot_node(host->dev, slot->id); | ||
| 1873 | ret = host->drv_data->setup_bus(host, slot_np, bus_width); | ||
| 1874 | if (ret) | ||
| 1875 | goto err_setup_bus; | ||
| 1876 | } | ||
| 1877 | |||
| 1878 | switch (bus_width) { | ||
| 1879 | case 8: | ||
| 1880 | mmc->caps |= MMC_CAP_8_BIT_DATA; | ||
| 1881 | case 4: | ||
| 1882 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
| 1883 | } | ||
| 1809 | 1884 | ||
| 1810 | if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED) | 1885 | if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED) |
| 1811 | mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; | 1886 | mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; |
| 1812 | 1887 | ||
| 1813 | if (mmc->caps2 & MMC_CAP2_POWEROFF_NOTIFY) | ||
| 1814 | mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT; | ||
| 1815 | else | ||
| 1816 | mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE; | ||
| 1817 | |||
| 1818 | if (host->pdata->blk_settings) { | 1888 | if (host->pdata->blk_settings) { |
| 1819 | mmc->max_segs = host->pdata->blk_settings->max_segs; | 1889 | mmc->max_segs = host->pdata->blk_settings->max_segs; |
| 1820 | mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; | 1890 | mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; |
| @@ -1850,7 +1920,6 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
| 1850 | else | 1920 | else |
| 1851 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); | 1921 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); |
| 1852 | 1922 | ||
| 1853 | host->slot[id] = slot; | ||
| 1854 | mmc_add_host(mmc); | 1923 | mmc_add_host(mmc); |
| 1855 | 1924 | ||
| 1856 | #if defined(CONFIG_DEBUG_FS) | 1925 | #if defined(CONFIG_DEBUG_FS) |
| @@ -1867,6 +1936,10 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
| 1867 | queue_work(host->card_workqueue, &host->card_work); | 1936 | queue_work(host->card_workqueue, &host->card_work); |
| 1868 | 1937 | ||
| 1869 | return 0; | 1938 | return 0; |
| 1939 | |||
| 1940 | err_setup_bus: | ||
| 1941 | mmc_free_host(mmc); | ||
| 1942 | return -EINVAL; | ||
| 1870 | } | 1943 | } |
| 1871 | 1944 | ||
| 1872 | static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) | 1945 | static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) |
| @@ -1884,10 +1957,10 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) | |||
| 1884 | static void dw_mci_init_dma(struct dw_mci *host) | 1957 | static void dw_mci_init_dma(struct dw_mci *host) |
| 1885 | { | 1958 | { |
| 1886 | /* Alloc memory for sg translation */ | 1959 | /* Alloc memory for sg translation */ |
| 1887 | host->sg_cpu = dma_alloc_coherent(&host->dev, PAGE_SIZE, | 1960 | host->sg_cpu = dma_alloc_coherent(host->dev, PAGE_SIZE, |
| 1888 | &host->sg_dma, GFP_KERNEL); | 1961 | &host->sg_dma, GFP_KERNEL); |
| 1889 | if (!host->sg_cpu) { | 1962 | if (!host->sg_cpu) { |
| 1890 | dev_err(&host->dev, "%s: could not alloc DMA memory\n", | 1963 | dev_err(host->dev, "%s: could not alloc DMA memory\n", |
| 1891 | __func__); | 1964 | __func__); |
| 1892 | goto no_dma; | 1965 | goto no_dma; |
| 1893 | } | 1966 | } |
| @@ -1895,6 +1968,7 @@ static void dw_mci_init_dma(struct dw_mci *host) | |||
| 1895 | /* Determine which DMA interface to use */ | 1968 | /* Determine which DMA interface to use */ |
| 1896 | #ifdef CONFIG_MMC_DW_IDMAC | 1969 | #ifdef CONFIG_MMC_DW_IDMAC |
| 1897 | host->dma_ops = &dw_mci_idmac_ops; | 1970 | host->dma_ops = &dw_mci_idmac_ops; |
| 1971 | dev_info(&host->dev, "Using internal DMA controller.\n"); | ||
| 1898 | #endif | 1972 | #endif |
| 1899 | 1973 | ||
| 1900 | if (!host->dma_ops) | 1974 | if (!host->dma_ops) |
| @@ -1903,12 +1977,12 @@ static void dw_mci_init_dma(struct dw_mci *host) | |||
| 1903 | if (host->dma_ops->init && host->dma_ops->start && | 1977 | if (host->dma_ops->init && host->dma_ops->start && |
| 1904 | host->dma_ops->stop && host->dma_ops->cleanup) { | 1978 | host->dma_ops->stop && host->dma_ops->cleanup) { |
| 1905 | if (host->dma_ops->init(host)) { | 1979 | if (host->dma_ops->init(host)) { |
| 1906 | dev_err(&host->dev, "%s: Unable to initialize " | 1980 | dev_err(host->dev, "%s: Unable to initialize " |
| 1907 | "DMA Controller.\n", __func__); | 1981 | "DMA Controller.\n", __func__); |
| 1908 | goto no_dma; | 1982 | goto no_dma; |
| 1909 | } | 1983 | } |
| 1910 | } else { | 1984 | } else { |
| 1911 | dev_err(&host->dev, "DMA initialization not found.\n"); | 1985 | dev_err(host->dev, "DMA initialization not found.\n"); |
| 1912 | goto no_dma; | 1986 | goto no_dma; |
| 1913 | } | 1987 | } |
| 1914 | 1988 | ||
| @@ -1916,7 +1990,7 @@ static void dw_mci_init_dma(struct dw_mci *host) | |||
| 1916 | return; | 1990 | return; |
| 1917 | 1991 | ||
| 1918 | no_dma: | 1992 | no_dma: |
| 1919 | dev_info(&host->dev, "Using PIO mode.\n"); | 1993 | dev_info(host->dev, "Using PIO mode.\n"); |
| 1920 | host->use_dma = 0; | 1994 | host->use_dma = 0; |
| 1921 | return; | 1995 | return; |
| 1922 | } | 1996 | } |
| @@ -1942,30 +2016,133 @@ static bool mci_wait_reset(struct device *dev, struct dw_mci *host) | |||
| 1942 | return false; | 2016 | return false; |
| 1943 | } | 2017 | } |
| 1944 | 2018 | ||
| 2019 | #ifdef CONFIG_OF | ||
| 2020 | static struct dw_mci_of_quirks { | ||
| 2021 | char *quirk; | ||
| 2022 | int id; | ||
| 2023 | } of_quirks[] = { | ||
| 2024 | { | ||
| 2025 | .quirk = "supports-highspeed", | ||
| 2026 | .id = DW_MCI_QUIRK_HIGHSPEED, | ||
| 2027 | }, { | ||
| 2028 | .quirk = "broken-cd", | ||
| 2029 | .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, | ||
| 2030 | }, | ||
| 2031 | }; | ||
| 2032 | |||
| 2033 | static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | ||
| 2034 | { | ||
| 2035 | struct dw_mci_board *pdata; | ||
| 2036 | struct device *dev = host->dev; | ||
| 2037 | struct device_node *np = dev->of_node; | ||
| 2038 | int idx, ret; | ||
| 2039 | |||
| 2040 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
| 2041 | if (!pdata) { | ||
| 2042 | dev_err(dev, "could not allocate memory for pdata\n"); | ||
| 2043 | return ERR_PTR(-ENOMEM); | ||
| 2044 | } | ||
| 2045 | |||
| 2046 | /* find out number of slots supported */ | ||
| 2047 | if (of_property_read_u32(dev->of_node, "num-slots", | ||
| 2048 | &pdata->num_slots)) { | ||
| 2049 | dev_info(dev, "num-slots property not found, " | ||
| 2050 | "assuming 1 slot is available\n"); | ||
| 2051 | pdata->num_slots = 1; | ||
| 2052 | } | ||
| 2053 | |||
| 2054 | /* get quirks */ | ||
| 2055 | for (idx = 0; idx < ARRAY_SIZE(of_quirks); idx++) | ||
| 2056 | if (of_get_property(np, of_quirks[idx].quirk, NULL)) | ||
| 2057 | pdata->quirks |= of_quirks[idx].id; | ||
| 2058 | |||
| 2059 | if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth)) | ||
| 2060 | dev_info(dev, "fifo-depth property not found, using " | ||
| 2061 | "value of FIFOTH register as default\n"); | ||
| 2062 | |||
| 2063 | of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); | ||
| 2064 | |||
| 2065 | if (host->drv_data->parse_dt) { | ||
| 2066 | ret = host->drv_data->parse_dt(host); | ||
| 2067 | if (ret) | ||
| 2068 | return ERR_PTR(ret); | ||
| 2069 | } | ||
| 2070 | |||
| 2071 | return pdata; | ||
| 2072 | } | ||
| 2073 | |||
| 2074 | #else /* CONFIG_OF */ | ||
| 2075 | static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | ||
| 2076 | { | ||
| 2077 | return ERR_PTR(-EINVAL); | ||
| 2078 | } | ||
| 2079 | #endif /* CONFIG_OF */ | ||
| 2080 | |||
| 1945 | int dw_mci_probe(struct dw_mci *host) | 2081 | int dw_mci_probe(struct dw_mci *host) |
| 1946 | { | 2082 | { |
| 1947 | int width, i, ret = 0; | 2083 | int width, i, ret = 0; |
| 1948 | u32 fifo_size; | 2084 | u32 fifo_size; |
| 2085 | int init_slots = 0; | ||
| 1949 | 2086 | ||
| 1950 | if (!host->pdata || !host->pdata->init) { | 2087 | if (!host->pdata) { |
| 1951 | dev_err(&host->dev, | 2088 | host->pdata = dw_mci_parse_dt(host); |
| 1952 | "Platform data must supply init function\n"); | 2089 | if (IS_ERR(host->pdata)) { |
| 1953 | return -ENODEV; | 2090 | dev_err(host->dev, "platform data not available\n"); |
| 2091 | return -EINVAL; | ||
| 2092 | } | ||
| 1954 | } | 2093 | } |
| 1955 | 2094 | ||
| 1956 | if (!host->pdata->select_slot && host->pdata->num_slots > 1) { | 2095 | if (!host->pdata->select_slot && host->pdata->num_slots > 1) { |
| 1957 | dev_err(&host->dev, | 2096 | dev_err(host->dev, |
| 1958 | "Platform data must supply select_slot function\n"); | 2097 | "Platform data must supply select_slot function\n"); |
| 1959 | return -ENODEV; | 2098 | return -ENODEV; |
| 1960 | } | 2099 | } |
| 1961 | 2100 | ||
| 1962 | if (!host->pdata->bus_hz) { | 2101 | host->biu_clk = clk_get(host->dev, "biu"); |
| 1963 | dev_err(&host->dev, | 2102 | if (IS_ERR(host->biu_clk)) { |
| 2103 | dev_dbg(host->dev, "biu clock not available\n"); | ||
| 2104 | } else { | ||
| 2105 | ret = clk_prepare_enable(host->biu_clk); | ||
| 2106 | if (ret) { | ||
| 2107 | dev_err(host->dev, "failed to enable biu clock\n"); | ||
| 2108 | clk_put(host->biu_clk); | ||
| 2109 | return ret; | ||
| 2110 | } | ||
| 2111 | } | ||
| 2112 | |||
| 2113 | host->ciu_clk = clk_get(host->dev, "ciu"); | ||
| 2114 | if (IS_ERR(host->ciu_clk)) { | ||
| 2115 | dev_dbg(host->dev, "ciu clock not available\n"); | ||
| 2116 | } else { | ||
| 2117 | ret = clk_prepare_enable(host->ciu_clk); | ||
| 2118 | if (ret) { | ||
| 2119 | dev_err(host->dev, "failed to enable ciu clock\n"); | ||
| 2120 | clk_put(host->ciu_clk); | ||
| 2121 | goto err_clk_biu; | ||
| 2122 | } | ||
| 2123 | } | ||
| 2124 | |||
| 2125 | if (IS_ERR(host->ciu_clk)) | ||
| 2126 | host->bus_hz = host->pdata->bus_hz; | ||
| 2127 | else | ||
| 2128 | host->bus_hz = clk_get_rate(host->ciu_clk); | ||
| 2129 | |||
| 2130 | if (host->drv_data->setup_clock) { | ||
| 2131 | ret = host->drv_data->setup_clock(host); | ||
| 2132 | if (ret) { | ||
| 2133 | dev_err(host->dev, | ||
| 2134 | "implementation specific clock setup failed\n"); | ||
| 2135 | goto err_clk_ciu; | ||
| 2136 | } | ||
| 2137 | } | ||
| 2138 | |||
| 2139 | if (!host->bus_hz) { | ||
| 2140 | dev_err(host->dev, | ||
| 1964 | "Platform data must supply bus speed\n"); | 2141 | "Platform data must supply bus speed\n"); |
| 1965 | return -ENODEV; | 2142 | ret = -ENODEV; |
| 2143 | goto err_clk_ciu; | ||
| 1966 | } | 2144 | } |
| 1967 | 2145 | ||
| 1968 | host->bus_hz = host->pdata->bus_hz; | ||
| 1969 | host->quirks = host->pdata->quirks; | 2146 | host->quirks = host->pdata->quirks; |
| 1970 | 2147 | ||
| 1971 | spin_lock_init(&host->lock); | 2148 | spin_lock_init(&host->lock); |
| @@ -1998,7 +2175,7 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 1998 | } | 2175 | } |
| 1999 | 2176 | ||
| 2000 | /* Reset all blocks */ | 2177 | /* Reset all blocks */ |
| 2001 | if (!mci_wait_reset(&host->dev, host)) | 2178 | if (!mci_wait_reset(host->dev, host)) |
| 2002 | return -ENODEV; | 2179 | return -ENODEV; |
| 2003 | 2180 | ||
| 2004 | host->dma_ops = host->pdata->dma_ops; | 2181 | host->dma_ops = host->pdata->dma_ops; |
| @@ -2054,10 +2231,18 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 2054 | /* We need at least one slot to succeed */ | 2231 | /* We need at least one slot to succeed */ |
| 2055 | for (i = 0; i < host->num_slots; i++) { | 2232 | for (i = 0; i < host->num_slots; i++) { |
| 2056 | ret = dw_mci_init_slot(host, i); | 2233 | ret = dw_mci_init_slot(host, i); |
| 2057 | if (ret) { | 2234 | if (ret) |
| 2058 | ret = -ENODEV; | 2235 | dev_dbg(host->dev, "slot %d init failed\n", i); |
| 2059 | goto err_init_slot; | 2236 | else |
| 2060 | } | 2237 | init_slots++; |
| 2238 | } | ||
| 2239 | |||
| 2240 | if (init_slots) { | ||
| 2241 | dev_info(host->dev, "%d slots initialized\n", init_slots); | ||
| 2242 | } else { | ||
| 2243 | dev_dbg(host->dev, "attempted to initialize %d slots, " | ||
| 2244 | "but failed on all\n", host->num_slots); | ||
| 2245 | goto err_init_slot; | ||
| 2061 | } | 2246 | } |
| 2062 | 2247 | ||
| 2063 | /* | 2248 | /* |
| @@ -2065,7 +2250,7 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 2065 | * Need to check the version-id and set data-offset for DATA register. | 2250 | * Need to check the version-id and set data-offset for DATA register. |
| 2066 | */ | 2251 | */ |
| 2067 | host->verid = SDMMC_GET_VERID(mci_readl(host, VERID)); | 2252 | host->verid = SDMMC_GET_VERID(mci_readl(host, VERID)); |
| 2068 | dev_info(&host->dev, "Version ID is %04x\n", host->verid); | 2253 | dev_info(host->dev, "Version ID is %04x\n", host->verid); |
| 2069 | 2254 | ||
| 2070 | if (host->verid < DW_MMC_240A) | 2255 | if (host->verid < DW_MMC_240A) |
| 2071 | host->data_offset = DATA_OFFSET; | 2256 | host->data_offset = DATA_OFFSET; |
| @@ -2082,22 +2267,16 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 2082 | DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); | 2267 | DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); |
| 2083 | mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ | 2268 | mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ |
| 2084 | 2269 | ||
| 2085 | dev_info(&host->dev, "DW MMC controller at irq %d, " | 2270 | dev_info(host->dev, "DW MMC controller at irq %d, " |
| 2086 | "%d bit host data width, " | 2271 | "%d bit host data width, " |
| 2087 | "%u deep fifo\n", | 2272 | "%u deep fifo\n", |
| 2088 | host->irq, width, fifo_size); | 2273 | host->irq, width, fifo_size); |
| 2089 | if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) | 2274 | if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) |
| 2090 | dev_info(&host->dev, "Internal DMAC interrupt fix enabled.\n"); | 2275 | dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); |
| 2091 | 2276 | ||
| 2092 | return 0; | 2277 | return 0; |
| 2093 | 2278 | ||
| 2094 | err_init_slot: | 2279 | err_init_slot: |
| 2095 | /* De-init any initialized slots */ | ||
| 2096 | while (i > 0) { | ||
| 2097 | if (host->slot[i]) | ||
| 2098 | dw_mci_cleanup_slot(host->slot[i], i); | ||
| 2099 | i--; | ||
| 2100 | } | ||
| 2101 | free_irq(host->irq, host); | 2280 | free_irq(host->irq, host); |
| 2102 | 2281 | ||
| 2103 | err_workqueue: | 2282 | err_workqueue: |
| @@ -2106,13 +2285,24 @@ err_workqueue: | |||
| 2106 | err_dmaunmap: | 2285 | err_dmaunmap: |
| 2107 | if (host->use_dma && host->dma_ops->exit) | 2286 | if (host->use_dma && host->dma_ops->exit) |
| 2108 | host->dma_ops->exit(host); | 2287 | host->dma_ops->exit(host); |
| 2109 | dma_free_coherent(&host->dev, PAGE_SIZE, | 2288 | dma_free_coherent(host->dev, PAGE_SIZE, |
| 2110 | host->sg_cpu, host->sg_dma); | 2289 | host->sg_cpu, host->sg_dma); |
| 2111 | 2290 | ||
| 2112 | if (host->vmmc) { | 2291 | if (host->vmmc) { |
| 2113 | regulator_disable(host->vmmc); | 2292 | regulator_disable(host->vmmc); |
| 2114 | regulator_put(host->vmmc); | 2293 | regulator_put(host->vmmc); |
| 2115 | } | 2294 | } |
| 2295 | |||
| 2296 | err_clk_ciu: | ||
| 2297 | if (!IS_ERR(host->ciu_clk)) { | ||
| 2298 | clk_disable_unprepare(host->ciu_clk); | ||
| 2299 | clk_put(host->ciu_clk); | ||
| 2300 | } | ||
| 2301 | err_clk_biu: | ||
| 2302 | if (!IS_ERR(host->biu_clk)) { | ||
| 2303 | clk_disable_unprepare(host->biu_clk); | ||
| 2304 | clk_put(host->biu_clk); | ||
| 2305 | } | ||
| 2116 | return ret; | 2306 | return ret; |
| 2117 | } | 2307 | } |
| 2118 | EXPORT_SYMBOL(dw_mci_probe); | 2308 | EXPORT_SYMBOL(dw_mci_probe); |
| @@ -2125,7 +2315,7 @@ void dw_mci_remove(struct dw_mci *host) | |||
| 2125 | mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ | 2315 | mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ |
| 2126 | 2316 | ||
| 2127 | for (i = 0; i < host->num_slots; i++) { | 2317 | for (i = 0; i < host->num_slots; i++) { |
| 2128 | dev_dbg(&host->dev, "remove slot %d\n", i); | 2318 | dev_dbg(host->dev, "remove slot %d\n", i); |
| 2129 | if (host->slot[i]) | 2319 | if (host->slot[i]) |
| 2130 | dw_mci_cleanup_slot(host->slot[i], i); | 2320 | dw_mci_cleanup_slot(host->slot[i], i); |
| 2131 | } | 2321 | } |
| @@ -2136,7 +2326,7 @@ void dw_mci_remove(struct dw_mci *host) | |||
| 2136 | 2326 | ||
| 2137 | free_irq(host->irq, host); | 2327 | free_irq(host->irq, host); |
| 2138 | destroy_workqueue(host->card_workqueue); | 2328 | destroy_workqueue(host->card_workqueue); |
| 2139 | dma_free_coherent(&host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); | 2329 | dma_free_coherent(host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); |
| 2140 | 2330 | ||
| 2141 | if (host->use_dma && host->dma_ops->exit) | 2331 | if (host->use_dma && host->dma_ops->exit) |
| 2142 | host->dma_ops->exit(host); | 2332 | host->dma_ops->exit(host); |
| @@ -2146,6 +2336,12 @@ void dw_mci_remove(struct dw_mci *host) | |||
| 2146 | regulator_put(host->vmmc); | 2336 | regulator_put(host->vmmc); |
| 2147 | } | 2337 | } |
| 2148 | 2338 | ||
| 2339 | if (!IS_ERR(host->ciu_clk)) | ||
| 2340 | clk_disable_unprepare(host->ciu_clk); | ||
| 2341 | if (!IS_ERR(host->biu_clk)) | ||
| 2342 | clk_disable_unprepare(host->biu_clk); | ||
| 2343 | clk_put(host->ciu_clk); | ||
| 2344 | clk_put(host->biu_clk); | ||
| 2149 | } | 2345 | } |
| 2150 | EXPORT_SYMBOL(dw_mci_remove); | 2346 | EXPORT_SYMBOL(dw_mci_remove); |
| 2151 | 2347 | ||
| @@ -2188,7 +2384,7 @@ int dw_mci_resume(struct dw_mci *host) | |||
| 2188 | if (host->vmmc) | 2384 | if (host->vmmc) |
| 2189 | regulator_enable(host->vmmc); | 2385 | regulator_enable(host->vmmc); |
| 2190 | 2386 | ||
| 2191 | if (!mci_wait_reset(&host->dev, host)) { | 2387 | if (!mci_wait_reset(host->dev, host)) { |
| 2192 | ret = -ENODEV; | 2388 | ret = -ENODEV; |
| 2193 | return ret; | 2389 | return ret; |
| 2194 | } | 2390 | } |
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 15c27e17c23f..53b8fd987e47 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h | |||
| @@ -182,4 +182,28 @@ extern int dw_mci_suspend(struct dw_mci *host); | |||
| 182 | extern int dw_mci_resume(struct dw_mci *host); | 182 | extern int dw_mci_resume(struct dw_mci *host); |
| 183 | #endif | 183 | #endif |
| 184 | 184 | ||
| 185 | /** | ||
| 186 | * dw_mci driver data - dw-mshc implementation specific driver data. | ||
| 187 | * @caps: mmc subsystem specified capabilities of the controller(s). | ||
| 188 | * @init: early implementation specific initialization. | ||
| 189 | * @setup_clock: implementation specific clock configuration. | ||
| 190 | * @prepare_command: handle CMD register extensions. | ||
| 191 | * @set_ios: handle bus specific extensions. | ||
| 192 | * @parse_dt: parse implementation specific device tree properties. | ||
| 193 | * @setup_bus: initialize io-interface | ||
| 194 | * | ||
| 195 | * Provide controller implementation specific extensions. The usage of this | ||
| 196 | * data structure is fully optional and usage of each member in this structure | ||
| 197 | * is optional as well. | ||
| 198 | */ | ||
| 199 | struct dw_mci_drv_data { | ||
| 200 | unsigned long *caps; | ||
| 201 | int (*init)(struct dw_mci *host); | ||
| 202 | int (*setup_clock)(struct dw_mci *host); | ||
| 203 | void (*prepare_command)(struct dw_mci *host, u32 *cmdr); | ||
| 204 | void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); | ||
| 205 | int (*parse_dt)(struct dw_mci *host); | ||
| 206 | int (*setup_bus)(struct dw_mci *host, | ||
| 207 | struct device_node *slot_np, u8 bus_width); | ||
| 208 | }; | ||
| 185 | #endif /* _DW_MMC_H_ */ | 209 | #endif /* _DW_MMC_H_ */ |
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 273306c68d58..a600eabbd6c3 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
| @@ -1532,20 +1532,7 @@ static struct spi_driver mmc_spi_driver = { | |||
| 1532 | .remove = __devexit_p(mmc_spi_remove), | 1532 | .remove = __devexit_p(mmc_spi_remove), |
| 1533 | }; | 1533 | }; |
| 1534 | 1534 | ||
| 1535 | 1535 | module_spi_driver(mmc_spi_driver); | |
| 1536 | static int __init mmc_spi_init(void) | ||
| 1537 | { | ||
| 1538 | return spi_register_driver(&mmc_spi_driver); | ||
| 1539 | } | ||
| 1540 | module_init(mmc_spi_init); | ||
| 1541 | |||
| 1542 | |||
| 1543 | static void __exit mmc_spi_exit(void) | ||
| 1544 | { | ||
| 1545 | spi_unregister_driver(&mmc_spi_driver); | ||
| 1546 | } | ||
| 1547 | module_exit(mmc_spi_exit); | ||
| 1548 | |||
| 1549 | 1536 | ||
| 1550 | MODULE_AUTHOR("Mike Lavender, David Brownell, " | 1537 | MODULE_AUTHOR("Mike Lavender, David Brownell, " |
| 1551 | "Hans-Peter Nilsson, Jan Nikitenko"); | 1538 | "Hans-Peter Nilsson, Jan Nikitenko"); |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 50ff19a62368..edc3e9baf0e7 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
| @@ -1309,14 +1309,10 @@ static int __devinit mmci_probe(struct amba_device *dev, | |||
| 1309 | goto host_free; | 1309 | goto host_free; |
| 1310 | } | 1310 | } |
| 1311 | 1311 | ||
| 1312 | ret = clk_prepare(host->clk); | 1312 | ret = clk_prepare_enable(host->clk); |
| 1313 | if (ret) | 1313 | if (ret) |
| 1314 | goto clk_free; | 1314 | goto clk_free; |
| 1315 | 1315 | ||
| 1316 | ret = clk_enable(host->clk); | ||
| 1317 | if (ret) | ||
| 1318 | goto clk_unprep; | ||
| 1319 | |||
| 1320 | host->plat = plat; | 1316 | host->plat = plat; |
| 1321 | host->variant = variant; | 1317 | host->variant = variant; |
| 1322 | host->mclk = clk_get_rate(host->clk); | 1318 | host->mclk = clk_get_rate(host->clk); |
| @@ -1515,9 +1511,7 @@ static int __devinit mmci_probe(struct amba_device *dev, | |||
| 1515 | err_gpio_cd: | 1511 | err_gpio_cd: |
| 1516 | iounmap(host->base); | 1512 | iounmap(host->base); |
| 1517 | clk_disable: | 1513 | clk_disable: |
| 1518 | clk_disable(host->clk); | 1514 | clk_disable_unprepare(host->clk); |
| 1519 | clk_unprep: | ||
| 1520 | clk_unprepare(host->clk); | ||
| 1521 | clk_free: | 1515 | clk_free: |
| 1522 | clk_put(host->clk); | 1516 | clk_put(host->clk); |
| 1523 | host_free: | 1517 | host_free: |
| @@ -1564,8 +1558,7 @@ static int __devexit mmci_remove(struct amba_device *dev) | |||
| 1564 | gpio_free(host->gpio_cd); | 1558 | gpio_free(host->gpio_cd); |
| 1565 | 1559 | ||
| 1566 | iounmap(host->base); | 1560 | iounmap(host->base); |
| 1567 | clk_disable(host->clk); | 1561 | clk_disable_unprepare(host->clk); |
| 1568 | clk_unprepare(host->clk); | ||
| 1569 | clk_put(host->clk); | 1562 | clk_put(host->clk); |
| 1570 | 1563 | ||
| 1571 | if (host->vcc) | 1564 | if (host->vcc) |
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 7b1161de01d6..565c2e4fac75 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include <mach/hardware.h> | 44 | #include <mach/hardware.h> |
| 45 | 45 | ||
| 46 | #define DRIVER_NAME "mxc-mmc" | 46 | #define DRIVER_NAME "mxc-mmc" |
| 47 | #define MXCMCI_TIMEOUT_MS 10000 | ||
| 47 | 48 | ||
| 48 | #define MMC_REG_STR_STP_CLK 0x00 | 49 | #define MMC_REG_STR_STP_CLK 0x00 |
| 49 | #define MMC_REG_STATUS 0x04 | 50 | #define MMC_REG_STATUS 0x04 |
| @@ -150,6 +151,8 @@ struct mxcmci_host { | |||
| 150 | int dmareq; | 151 | int dmareq; |
| 151 | struct dma_slave_config dma_slave_config; | 152 | struct dma_slave_config dma_slave_config; |
| 152 | struct imx_dma_data dma_data; | 153 | struct imx_dma_data dma_data; |
| 154 | |||
| 155 | struct timer_list watchdog; | ||
| 153 | }; | 156 | }; |
| 154 | 157 | ||
| 155 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); | 158 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); |
| @@ -271,9 +274,32 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | |||
| 271 | dmaengine_submit(host->desc); | 274 | dmaengine_submit(host->desc); |
| 272 | dma_async_issue_pending(host->dma); | 275 | dma_async_issue_pending(host->dma); |
| 273 | 276 | ||
| 277 | mod_timer(&host->watchdog, jiffies + msecs_to_jiffies(MXCMCI_TIMEOUT_MS)); | ||
| 278 | |||
| 274 | return 0; | 279 | return 0; |
| 275 | } | 280 | } |
| 276 | 281 | ||
| 282 | static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat); | ||
| 283 | static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat); | ||
| 284 | |||
| 285 | static void mxcmci_dma_callback(void *data) | ||
| 286 | { | ||
| 287 | struct mxcmci_host *host = data; | ||
| 288 | u32 stat; | ||
| 289 | |||
| 290 | del_timer(&host->watchdog); | ||
| 291 | |||
| 292 | stat = readl(host->base + MMC_REG_STATUS); | ||
| 293 | writel(stat & ~STATUS_DATA_TRANS_DONE, host->base + MMC_REG_STATUS); | ||
| 294 | |||
| 295 | dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); | ||
| 296 | |||
| 297 | if (stat & STATUS_READ_OP_DONE) | ||
| 298 | writel(STATUS_READ_OP_DONE, host->base + MMC_REG_STATUS); | ||
| 299 | |||
| 300 | mxcmci_data_done(host, stat); | ||
| 301 | } | ||
| 302 | |||
| 277 | static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, | 303 | static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, |
| 278 | unsigned int cmdat) | 304 | unsigned int cmdat) |
| 279 | { | 305 | { |
| @@ -305,8 +331,14 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, | |||
| 305 | 331 | ||
| 306 | int_cntr = INT_END_CMD_RES_EN; | 332 | int_cntr = INT_END_CMD_RES_EN; |
| 307 | 333 | ||
| 308 | if (mxcmci_use_dma(host)) | 334 | if (mxcmci_use_dma(host)) { |
| 309 | int_cntr |= INT_READ_OP_EN | INT_WRITE_OP_DONE_EN; | 335 | if (host->dma_dir == DMA_FROM_DEVICE) { |
| 336 | host->desc->callback = mxcmci_dma_callback; | ||
| 337 | host->desc->callback_param = host; | ||
| 338 | } else { | ||
| 339 | int_cntr |= INT_WRITE_OP_DONE_EN; | ||
| 340 | } | ||
| 341 | } | ||
| 310 | 342 | ||
| 311 | spin_lock_irqsave(&host->lock, flags); | 343 | spin_lock_irqsave(&host->lock, flags); |
| 312 | if (host->use_sdio) | 344 | if (host->use_sdio) |
| @@ -345,11 +377,9 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat) | |||
| 345 | struct mmc_data *data = host->data; | 377 | struct mmc_data *data = host->data; |
| 346 | int data_error; | 378 | int data_error; |
| 347 | 379 | ||
| 348 | if (mxcmci_use_dma(host)) { | 380 | if (mxcmci_use_dma(host)) |
| 349 | dmaengine_terminate_all(host->dma); | ||
| 350 | dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, | 381 | dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, |
| 351 | host->dma_dir); | 382 | host->dma_dir); |
| 352 | } | ||
| 353 | 383 | ||
| 354 | if (stat & STATUS_ERR_MASK) { | 384 | if (stat & STATUS_ERR_MASK) { |
| 355 | dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", | 385 | dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", |
| @@ -624,8 +654,10 @@ static irqreturn_t mxcmci_irq(int irq, void *devid) | |||
| 624 | mxcmci_cmd_done(host, stat); | 654 | mxcmci_cmd_done(host, stat); |
| 625 | 655 | ||
| 626 | if (mxcmci_use_dma(host) && | 656 | if (mxcmci_use_dma(host) && |
| 627 | (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) | 657 | (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) { |
| 658 | del_timer(&host->watchdog); | ||
| 628 | mxcmci_data_done(host, stat); | 659 | mxcmci_data_done(host, stat); |
| 660 | } | ||
| 629 | 661 | ||
| 630 | if (host->default_irq_mask && | 662 | if (host->default_irq_mask && |
| 631 | (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL))) | 663 | (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL))) |
| @@ -836,6 +868,34 @@ static bool filter(struct dma_chan *chan, void *param) | |||
| 836 | return true; | 868 | return true; |
| 837 | } | 869 | } |
| 838 | 870 | ||
| 871 | static void mxcmci_watchdog(unsigned long data) | ||
| 872 | { | ||
| 873 | struct mmc_host *mmc = (struct mmc_host *)data; | ||
| 874 | struct mxcmci_host *host = mmc_priv(mmc); | ||
| 875 | struct mmc_request *req = host->req; | ||
| 876 | unsigned int stat = readl(host->base + MMC_REG_STATUS); | ||
| 877 | |||
| 878 | if (host->dma_dir == DMA_FROM_DEVICE) { | ||
| 879 | dmaengine_terminate_all(host->dma); | ||
| 880 | dev_err(mmc_dev(host->mmc), | ||
| 881 | "%s: read time out (status = 0x%08x)\n", | ||
| 882 | __func__, stat); | ||
| 883 | } else { | ||
| 884 | dev_err(mmc_dev(host->mmc), | ||
| 885 | "%s: write time out (status = 0x%08x)\n", | ||
| 886 | __func__, stat); | ||
| 887 | mxcmci_softreset(host); | ||
| 888 | } | ||
| 889 | |||
| 890 | /* Mark transfer as erroneus and inform the upper layers */ | ||
| 891 | |||
| 892 | host->data->error = -ETIMEDOUT; | ||
| 893 | host->req = NULL; | ||
| 894 | host->cmd = NULL; | ||
| 895 | host->data = NULL; | ||
| 896 | mmc_request_done(host->mmc, req); | ||
| 897 | } | ||
| 898 | |||
| 839 | static const struct mmc_host_ops mxcmci_ops = { | 899 | static const struct mmc_host_ops mxcmci_ops = { |
| 840 | .request = mxcmci_request, | 900 | .request = mxcmci_request, |
| 841 | .set_ios = mxcmci_set_ios, | 901 | .set_ios = mxcmci_set_ios, |
| @@ -968,6 +1028,10 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
| 968 | 1028 | ||
| 969 | mmc_add_host(mmc); | 1029 | mmc_add_host(mmc); |
| 970 | 1030 | ||
| 1031 | init_timer(&host->watchdog); | ||
| 1032 | host->watchdog.function = &mxcmci_watchdog; | ||
| 1033 | host->watchdog.data = (unsigned long)mmc; | ||
| 1034 | |||
| 971 | return 0; | 1035 | return 0; |
| 972 | 1036 | ||
| 973 | out_free_irq: | 1037 | out_free_irq: |
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index c6259a829544..48ad361613ef 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
| @@ -27,16 +27,10 @@ | |||
| 27 | #include <linux/mmc/card.h> | 27 | #include <linux/mmc/card.h> |
| 28 | #include <linux/clk.h> | 28 | #include <linux/clk.h> |
| 29 | #include <linux/scatterlist.h> | 29 | #include <linux/scatterlist.h> |
| 30 | #include <linux/i2c/tps65010.h> | ||
| 31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 32 | 31 | ||
| 33 | #include <asm/io.h> | ||
| 34 | #include <asm/irq.h> | ||
| 35 | |||
| 36 | #include <plat/mmc.h> | 32 | #include <plat/mmc.h> |
| 37 | #include <asm/gpio.h> | ||
| 38 | #include <plat/dma.h> | 33 | #include <plat/dma.h> |
| 39 | #include <plat/fpga.h> | ||
| 40 | 34 | ||
| 41 | #define OMAP_MMC_REG_CMD 0x00 | 35 | #define OMAP_MMC_REG_CMD 0x00 |
| 42 | #define OMAP_MMC_REG_ARGL 0x01 | 36 | #define OMAP_MMC_REG_ARGL 0x01 |
| @@ -105,7 +99,6 @@ struct mmc_omap_slot { | |||
| 105 | u16 saved_con; | 99 | u16 saved_con; |
| 106 | u16 bus_mode; | 100 | u16 bus_mode; |
| 107 | unsigned int fclk_freq; | 101 | unsigned int fclk_freq; |
| 108 | unsigned powered:1; | ||
| 109 | 102 | ||
| 110 | struct tasklet_struct cover_tasklet; | 103 | struct tasklet_struct cover_tasklet; |
| 111 | struct timer_list cover_timer; | 104 | struct timer_list cover_timer; |
| @@ -137,7 +130,6 @@ struct mmc_omap_host { | |||
| 137 | unsigned int phys_base; | 130 | unsigned int phys_base; |
| 138 | int irq; | 131 | int irq; |
| 139 | unsigned char bus_mode; | 132 | unsigned char bus_mode; |
| 140 | unsigned char hw_bus_mode; | ||
| 141 | unsigned int reg_shift; | 133 | unsigned int reg_shift; |
| 142 | 134 | ||
| 143 | struct work_struct cmd_abort_work; | 135 | struct work_struct cmd_abort_work; |
| @@ -695,22 +687,29 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write) | |||
| 695 | host->buffer += nwords; | 687 | host->buffer += nwords; |
| 696 | } | 688 | } |
| 697 | 689 | ||
| 698 | static inline void mmc_omap_report_irq(u16 status) | 690 | #ifdef CONFIG_MMC_DEBUG |
| 691 | static void mmc_omap_report_irq(struct mmc_omap_host *host, u16 status) | ||
| 699 | { | 692 | { |
| 700 | static const char *mmc_omap_status_bits[] = { | 693 | static const char *mmc_omap_status_bits[] = { |
| 701 | "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO", | 694 | "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO", |
| 702 | "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR" | 695 | "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR" |
| 703 | }; | 696 | }; |
| 704 | int i, c = 0; | 697 | int i; |
| 698 | char res[64], *buf = res; | ||
| 699 | |||
| 700 | buf += sprintf(buf, "MMC IRQ 0x%x:", status); | ||
| 705 | 701 | ||
| 706 | for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++) | 702 | for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++) |
| 707 | if (status & (1 << i)) { | 703 | if (status & (1 << i)) |
| 708 | if (c) | 704 | buf += sprintf(buf, " %s", mmc_omap_status_bits[i]); |
| 709 | printk(" "); | 705 | dev_vdbg(mmc_dev(host->mmc), "%s\n", res); |
| 710 | printk("%s", mmc_omap_status_bits[i]); | ||
| 711 | c++; | ||
| 712 | } | ||
| 713 | } | 706 | } |
| 707 | #else | ||
| 708 | static void mmc_omap_report_irq(struct mmc_omap_host *host, u16 status) | ||
| 709 | { | ||
| 710 | } | ||
| 711 | #endif | ||
| 712 | |||
| 714 | 713 | ||
| 715 | static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | 714 | static irqreturn_t mmc_omap_irq(int irq, void *dev_id) |
| 716 | { | 715 | { |
| @@ -744,12 +743,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
| 744 | cmd = host->cmd->opcode; | 743 | cmd = host->cmd->opcode; |
| 745 | else | 744 | else |
| 746 | cmd = -1; | 745 | cmd = -1; |
| 747 | #ifdef CONFIG_MMC_DEBUG | ||
| 748 | dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ", | 746 | dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ", |
| 749 | status, cmd); | 747 | status, cmd); |
| 750 | mmc_omap_report_irq(status); | 748 | mmc_omap_report_irq(host, status); |
| 751 | printk("\n"); | 749 | |
| 752 | #endif | ||
| 753 | if (host->total_bytes_left) { | 750 | if (host->total_bytes_left) { |
| 754 | if ((status & OMAP_MMC_STAT_A_FULL) || | 751 | if ((status & OMAP_MMC_STAT_A_FULL) || |
| 755 | (status & OMAP_MMC_STAT_END_OF_DATA)) | 752 | (status & OMAP_MMC_STAT_END_OF_DATA)) |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 38adc330c007..54bfd0cc106b 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
| @@ -35,7 +35,6 @@ | |||
| 35 | #include <linux/mmc/core.h> | 35 | #include <linux/mmc/core.h> |
| 36 | #include <linux/mmc/mmc.h> | 36 | #include <linux/mmc/mmc.h> |
| 37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
| 38 | #include <linux/semaphore.h> | ||
| 39 | #include <linux/gpio.h> | 38 | #include <linux/gpio.h> |
| 40 | #include <linux/regulator/consumer.h> | 39 | #include <linux/regulator/consumer.h> |
| 41 | #include <linux/pm_runtime.h> | 40 | #include <linux/pm_runtime.h> |
| @@ -44,7 +43,6 @@ | |||
| 44 | #include <plat/cpu.h> | 43 | #include <plat/cpu.h> |
| 45 | 44 | ||
| 46 | /* OMAP HSMMC Host Controller Registers */ | 45 | /* OMAP HSMMC Host Controller Registers */ |
| 47 | #define OMAP_HSMMC_SYSCONFIG 0x0010 | ||
| 48 | #define OMAP_HSMMC_SYSSTATUS 0x0014 | 46 | #define OMAP_HSMMC_SYSSTATUS 0x0014 |
| 49 | #define OMAP_HSMMC_CON 0x002C | 47 | #define OMAP_HSMMC_CON 0x002C |
| 50 | #define OMAP_HSMMC_BLK 0x0104 | 48 | #define OMAP_HSMMC_BLK 0x0104 |
| @@ -161,8 +159,6 @@ struct omap_hsmmc_host { | |||
| 161 | unsigned int dma_sg_idx; | 159 | unsigned int dma_sg_idx; |
| 162 | unsigned char bus_mode; | 160 | unsigned char bus_mode; |
| 163 | unsigned char power_mode; | 161 | unsigned char power_mode; |
| 164 | u32 *buffer; | ||
| 165 | u32 bytesleft; | ||
| 166 | int suspended; | 162 | int suspended; |
| 167 | int irq; | 163 | int irq; |
| 168 | int use_dma, dma_ch; | 164 | int use_dma, dma_ch; |
| @@ -171,7 +167,6 @@ struct omap_hsmmc_host { | |||
| 171 | int slot_id; | 167 | int slot_id; |
| 172 | int response_busy; | 168 | int response_busy; |
| 173 | int context_loss; | 169 | int context_loss; |
| 174 | int vdd; | ||
| 175 | int protect_card; | 170 | int protect_card; |
| 176 | int reqs_blocked; | 171 | int reqs_blocked; |
| 177 | int use_reg; | 172 | int use_reg; |
| @@ -300,12 +295,12 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | |||
| 300 | struct regulator *reg; | 295 | struct regulator *reg; |
| 301 | int ocr_value = 0; | 296 | int ocr_value = 0; |
| 302 | 297 | ||
| 303 | mmc_slot(host).set_power = omap_hsmmc_set_power; | ||
| 304 | |||
| 305 | reg = regulator_get(host->dev, "vmmc"); | 298 | reg = regulator_get(host->dev, "vmmc"); |
| 306 | if (IS_ERR(reg)) { | 299 | if (IS_ERR(reg)) { |
| 307 | dev_dbg(host->dev, "vmmc regulator missing\n"); | 300 | dev_dbg(host->dev, "vmmc regulator missing\n"); |
| 301 | return PTR_ERR(reg); | ||
| 308 | } else { | 302 | } else { |
| 303 | mmc_slot(host).set_power = omap_hsmmc_set_power; | ||
| 309 | host->vcc = reg; | 304 | host->vcc = reg; |
| 310 | ocr_value = mmc_regulator_get_ocrmask(reg); | 305 | ocr_value = mmc_regulator_get_ocrmask(reg); |
| 311 | if (!mmc_slot(host).ocr_mask) { | 306 | if (!mmc_slot(host).ocr_mask) { |
| @@ -495,7 +490,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host) | |||
| 495 | unsigned long regval; | 490 | unsigned long regval; |
| 496 | unsigned long timeout; | 491 | unsigned long timeout; |
| 497 | 492 | ||
| 498 | dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock); | 493 | dev_vdbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock); |
| 499 | 494 | ||
| 500 | omap_hsmmc_stop_clock(host); | 495 | omap_hsmmc_stop_clock(host); |
| 501 | 496 | ||
| @@ -579,21 +574,8 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | |||
| 579 | if (host->context_loss == context_loss) | 574 | if (host->context_loss == context_loss) |
| 580 | return 1; | 575 | return 1; |
| 581 | 576 | ||
| 582 | /* Wait for hardware reset */ | 577 | if (!OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) |
| 583 | timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); | 578 | return 1; |
| 584 | while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE | ||
| 585 | && time_before(jiffies, timeout)) | ||
| 586 | ; | ||
| 587 | |||
| 588 | /* Do software reset */ | ||
| 589 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, SOFTRESET); | ||
| 590 | timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); | ||
| 591 | while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE | ||
| 592 | && time_before(jiffies, timeout)) | ||
| 593 | ; | ||
| 594 | |||
| 595 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, | ||
| 596 | OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE); | ||
| 597 | 579 | ||
| 598 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { | 580 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { |
| 599 | if (host->power_mode != MMC_POWER_OFF && | 581 | if (host->power_mode != MMC_POWER_OFF && |
| @@ -745,7 +727,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, | |||
| 745 | { | 727 | { |
| 746 | int cmdreg = 0, resptype = 0, cmdtype = 0; | 728 | int cmdreg = 0, resptype = 0, cmdtype = 0; |
| 747 | 729 | ||
| 748 | dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n", | 730 | dev_vdbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n", |
| 749 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); | 731 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); |
| 750 | host->cmd = cmd; | 732 | host->cmd = cmd; |
| 751 | 733 | ||
| @@ -934,7 +916,7 @@ static void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, u32 status) | |||
| 934 | buf += len; | 916 | buf += len; |
| 935 | } | 917 | } |
| 936 | 918 | ||
| 937 | dev_dbg(mmc_dev(host->mmc), "%s\n", res); | 919 | dev_vdbg(mmc_dev(host->mmc), "%s\n", res); |
| 938 | } | 920 | } |
| 939 | #else | 921 | #else |
| 940 | static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, | 922 | static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, |
| @@ -981,72 +963,40 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, | |||
| 981 | __func__); | 963 | __func__); |
| 982 | } | 964 | } |
| 983 | 965 | ||
| 966 | static void hsmmc_command_incomplete(struct omap_hsmmc_host *host, int err) | ||
| 967 | { | ||
| 968 | omap_hsmmc_reset_controller_fsm(host, SRC); | ||
| 969 | host->cmd->error = err; | ||
| 970 | |||
| 971 | if (host->data) { | ||
| 972 | omap_hsmmc_reset_controller_fsm(host, SRD); | ||
| 973 | omap_hsmmc_dma_cleanup(host, err); | ||
| 974 | } | ||
| 975 | |||
| 976 | } | ||
| 977 | |||
| 984 | static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) | 978 | static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) |
| 985 | { | 979 | { |
| 986 | struct mmc_data *data; | 980 | struct mmc_data *data; |
| 987 | int end_cmd = 0, end_trans = 0; | 981 | int end_cmd = 0, end_trans = 0; |
| 988 | 982 | ||
| 989 | if (!host->req_in_progress) { | ||
| 990 | do { | ||
| 991 | OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
| 992 | /* Flush posted write */ | ||
| 993 | status = OMAP_HSMMC_READ(host->base, STAT); | ||
| 994 | } while (status & INT_EN_MASK); | ||
| 995 | return; | ||
| 996 | } | ||
| 997 | |||
| 998 | data = host->data; | 983 | data = host->data; |
| 999 | dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); | 984 | dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); |
| 1000 | 985 | ||
| 1001 | if (status & ERR) { | 986 | if (status & ERR) { |
| 1002 | omap_hsmmc_dbg_report_irq(host, status); | 987 | omap_hsmmc_dbg_report_irq(host, status); |
| 1003 | if ((status & CMD_TIMEOUT) || | 988 | if (status & (CMD_TIMEOUT | DATA_TIMEOUT)) |
| 1004 | (status & CMD_CRC)) { | 989 | hsmmc_command_incomplete(host, -ETIMEDOUT); |
| 1005 | if (host->cmd) { | 990 | else if (status & (CMD_CRC | DATA_CRC)) |
| 1006 | if (status & CMD_TIMEOUT) { | 991 | hsmmc_command_incomplete(host, -EILSEQ); |
| 1007 | omap_hsmmc_reset_controller_fsm(host, | 992 | |
| 1008 | SRC); | 993 | end_cmd = 1; |
| 1009 | host->cmd->error = -ETIMEDOUT; | 994 | if (host->data || host->response_busy) { |
| 1010 | } else { | 995 | end_trans = 1; |
| 1011 | host->cmd->error = -EILSEQ; | 996 | host->response_busy = 0; |
| 1012 | } | ||
| 1013 | end_cmd = 1; | ||
| 1014 | } | ||
| 1015 | if (host->data || host->response_busy) { | ||
| 1016 | if (host->data) | ||
| 1017 | omap_hsmmc_dma_cleanup(host, | ||
| 1018 | -ETIMEDOUT); | ||
| 1019 | host->response_busy = 0; | ||
| 1020 | omap_hsmmc_reset_controller_fsm(host, SRD); | ||
| 1021 | } | ||
| 1022 | } | ||
| 1023 | if ((status & DATA_TIMEOUT) || | ||
| 1024 | (status & DATA_CRC)) { | ||
| 1025 | if (host->data || host->response_busy) { | ||
| 1026 | int err = (status & DATA_TIMEOUT) ? | ||
| 1027 | -ETIMEDOUT : -EILSEQ; | ||
| 1028 | |||
| 1029 | if (host->data) | ||
| 1030 | omap_hsmmc_dma_cleanup(host, err); | ||
| 1031 | else | ||
| 1032 | host->mrq->cmd->error = err; | ||
| 1033 | host->response_busy = 0; | ||
| 1034 | omap_hsmmc_reset_controller_fsm(host, SRD); | ||
| 1035 | end_trans = 1; | ||
| 1036 | } | ||
| 1037 | } | ||
| 1038 | if (status & CARD_ERR) { | ||
| 1039 | dev_dbg(mmc_dev(host->mmc), | ||
| 1040 | "Ignoring card err CMD%d\n", host->cmd->opcode); | ||
| 1041 | if (host->cmd) | ||
| 1042 | end_cmd = 1; | ||
| 1043 | if (host->data) | ||
| 1044 | end_trans = 1; | ||
| 1045 | } | 997 | } |
| 1046 | } | 998 | } |
| 1047 | 999 | ||
| 1048 | OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
| 1049 | |||
| 1050 | if (end_cmd || ((status & CC) && host->cmd)) | 1000 | if (end_cmd || ((status & CC) && host->cmd)) |
| 1051 | omap_hsmmc_cmd_done(host, host->cmd); | 1001 | omap_hsmmc_cmd_done(host, host->cmd); |
| 1052 | if ((end_trans || (status & TC)) && host->mrq) | 1002 | if ((end_trans || (status & TC)) && host->mrq) |
| @@ -1062,11 +1012,13 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) | |||
| 1062 | int status; | 1012 | int status; |
| 1063 | 1013 | ||
| 1064 | status = OMAP_HSMMC_READ(host->base, STAT); | 1014 | status = OMAP_HSMMC_READ(host->base, STAT); |
| 1065 | do { | 1015 | while (status & INT_EN_MASK && host->req_in_progress) { |
| 1066 | omap_hsmmc_do_irq(host, status); | 1016 | omap_hsmmc_do_irq(host, status); |
| 1017 | |||
| 1067 | /* Flush posted write */ | 1018 | /* Flush posted write */ |
| 1019 | OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
| 1068 | status = OMAP_HSMMC_READ(host->base, STAT); | 1020 | status = OMAP_HSMMC_READ(host->base, STAT); |
| 1069 | } while (status & INT_EN_MASK); | 1021 | } |
| 1070 | 1022 | ||
| 1071 | return IRQ_HANDLED; | 1023 | return IRQ_HANDLED; |
| 1072 | } | 1024 | } |
| @@ -1501,12 +1453,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 1501 | case MMC_POWER_OFF: | 1453 | case MMC_POWER_OFF: |
| 1502 | mmc_slot(host).set_power(host->dev, host->slot_id, | 1454 | mmc_slot(host).set_power(host->dev, host->slot_id, |
| 1503 | 0, 0); | 1455 | 0, 0); |
| 1504 | host->vdd = 0; | ||
| 1505 | break; | 1456 | break; |
| 1506 | case MMC_POWER_UP: | 1457 | case MMC_POWER_UP: |
| 1507 | mmc_slot(host).set_power(host->dev, host->slot_id, | 1458 | mmc_slot(host).set_power(host->dev, host->slot_id, |
| 1508 | 1, ios->vdd); | 1459 | 1, ios->vdd); |
| 1509 | host->vdd = ios->vdd; | ||
| 1510 | break; | 1460 | break; |
| 1511 | case MMC_POWER_ON: | 1461 | case MMC_POWER_ON: |
| 1512 | do_send_init_stream = 1; | 1462 | do_send_init_stream = 1; |
| @@ -1598,10 +1548,6 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) | |||
| 1598 | value = OMAP_HSMMC_READ(host->base, CAPA); | 1548 | value = OMAP_HSMMC_READ(host->base, CAPA); |
| 1599 | OMAP_HSMMC_WRITE(host->base, CAPA, value | capa); | 1549 | OMAP_HSMMC_WRITE(host->base, CAPA, value | capa); |
| 1600 | 1550 | ||
| 1601 | /* Set the controller to AUTO IDLE mode */ | ||
| 1602 | value = OMAP_HSMMC_READ(host->base, SYSCONFIG); | ||
| 1603 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE); | ||
| 1604 | |||
| 1605 | /* Set SD bus power bit */ | 1551 | /* Set SD bus power bit */ |
| 1606 | set_sd_bus_power(host); | 1552 | set_sd_bus_power(host); |
| 1607 | } | 1553 | } |
| @@ -1659,8 +1605,6 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data) | |||
| 1659 | 1605 | ||
| 1660 | pm_runtime_get_sync(host->dev); | 1606 | pm_runtime_get_sync(host->dev); |
| 1661 | 1607 | ||
| 1662 | seq_printf(s, "SYSCONFIG:\t0x%08x\n", | ||
| 1663 | OMAP_HSMMC_READ(host->base, SYSCONFIG)); | ||
| 1664 | seq_printf(s, "CON:\t\t0x%08x\n", | 1608 | seq_printf(s, "CON:\t\t0x%08x\n", |
| 1665 | OMAP_HSMMC_READ(host->base, CON)); | 1609 | OMAP_HSMMC_READ(host->base, CON)); |
| 1666 | seq_printf(s, "HCTL:\t\t0x%08x\n", | 1610 | seq_printf(s, "HCTL:\t\t0x%08x\n", |
| @@ -2105,8 +2049,7 @@ static int omap_hsmmc_suspend(struct device *dev) | |||
| 2105 | if (ret) { | 2049 | if (ret) { |
| 2106 | host->suspended = 0; | 2050 | host->suspended = 0; |
| 2107 | if (host->pdata->resume) { | 2051 | if (host->pdata->resume) { |
| 2108 | ret = host->pdata->resume(dev, host->slot_id); | 2052 | if (host->pdata->resume(dev, host->slot_id)) |
| 2109 | if (ret) | ||
| 2110 | dev_dbg(dev, "Unmask interrupt failed\n"); | 2053 | dev_dbg(dev, "Unmask interrupt failed\n"); |
| 2111 | } | 2054 | } |
| 2112 | goto err; | 2055 | goto err; |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index ca3915dac03d..3f9d6d577a91 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
| @@ -30,6 +30,9 @@ | |||
| 30 | #include <linux/regulator/consumer.h> | 30 | #include <linux/regulator/consumer.h> |
| 31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
| 32 | #include <linux/gfp.h> | 32 | #include <linux/gfp.h> |
| 33 | #include <linux/of.h> | ||
| 34 | #include <linux/of_gpio.h> | ||
| 35 | #include <linux/of_device.h> | ||
| 33 | 36 | ||
| 34 | #include <asm/sizes.h> | 37 | #include <asm/sizes.h> |
| 35 | 38 | ||
| @@ -573,6 +576,50 @@ static irqreturn_t pxamci_detect_irq(int irq, void *devid) | |||
| 573 | return IRQ_HANDLED; | 576 | return IRQ_HANDLED; |
| 574 | } | 577 | } |
| 575 | 578 | ||
| 579 | #ifdef CONFIG_OF | ||
| 580 | static const struct of_device_id pxa_mmc_dt_ids[] = { | ||
| 581 | { .compatible = "marvell,pxa-mmc" }, | ||
| 582 | { } | ||
| 583 | }; | ||
| 584 | |||
| 585 | MODULE_DEVICE_TABLE(of, pxa_mmc_dt_ids); | ||
| 586 | |||
| 587 | static int __devinit pxamci_of_init(struct platform_device *pdev) | ||
| 588 | { | ||
| 589 | struct device_node *np = pdev->dev.of_node; | ||
| 590 | struct pxamci_platform_data *pdata; | ||
| 591 | u32 tmp; | ||
| 592 | |||
| 593 | if (!np) | ||
| 594 | return 0; | ||
| 595 | |||
| 596 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
| 597 | if (!pdata) | ||
| 598 | return -ENOMEM; | ||
| 599 | |||
| 600 | pdata->gpio_card_detect = | ||
| 601 | of_get_named_gpio(np, "cd-gpios", 0); | ||
| 602 | pdata->gpio_card_ro = | ||
| 603 | of_get_named_gpio(np, "wp-gpios", 0); | ||
| 604 | |||
| 605 | /* pxa-mmc specific */ | ||
| 606 | pdata->gpio_power = | ||
| 607 | of_get_named_gpio(np, "pxa-mmc,gpio-power", 0); | ||
| 608 | |||
| 609 | if (of_property_read_u32(np, "pxa-mmc,detect-delay-ms", &tmp) == 0) | ||
| 610 | pdata->detect_delay_ms = tmp; | ||
| 611 | |||
| 612 | pdev->dev.platform_data = pdata; | ||
| 613 | |||
| 614 | return 0; | ||
| 615 | } | ||
| 616 | #else | ||
| 617 | static int __devinit pxamci_of_init(struct platform_device *pdev) | ||
| 618 | { | ||
| 619 | return 0; | ||
| 620 | } | ||
| 621 | #endif | ||
| 622 | |||
| 576 | static int pxamci_probe(struct platform_device *pdev) | 623 | static int pxamci_probe(struct platform_device *pdev) |
| 577 | { | 624 | { |
| 578 | struct mmc_host *mmc; | 625 | struct mmc_host *mmc; |
| @@ -580,6 +627,10 @@ static int pxamci_probe(struct platform_device *pdev) | |||
| 580 | struct resource *r, *dmarx, *dmatx; | 627 | struct resource *r, *dmarx, *dmatx; |
| 581 | int ret, irq, gpio_cd = -1, gpio_ro = -1, gpio_power = -1; | 628 | int ret, irq, gpio_cd = -1, gpio_ro = -1, gpio_power = -1; |
| 582 | 629 | ||
| 630 | ret = pxamci_of_init(pdev); | ||
| 631 | if (ret) | ||
| 632 | return ret; | ||
| 633 | |||
| 583 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 634 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 584 | irq = platform_get_irq(pdev, 0); | 635 | irq = platform_get_irq(pdev, 0); |
| 585 | if (!r || irq < 0) | 636 | if (!r || irq < 0) |
| @@ -866,6 +917,7 @@ static struct platform_driver pxamci_driver = { | |||
| 866 | .driver = { | 917 | .driver = { |
| 867 | .name = DRIVER_NAME, | 918 | .name = DRIVER_NAME, |
| 868 | .owner = THIS_MODULE, | 919 | .owner = THIS_MODULE, |
| 920 | .of_match_table = of_match_ptr(pxa_mmc_dt_ids), | ||
| 869 | #ifdef CONFIG_PM | 921 | #ifdef CONFIG_PM |
| 870 | .pm = &pxamci_pm_ops, | 922 | .pm = &pxamci_pm_ops, |
| 871 | #endif | 923 | #endif |
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index a6e53a1ebb08..90140eb03e36 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
| 25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
| 26 | #include <linux/mmc/host.h> | 26 | #include <linux/mmc/host.h> |
| 27 | #include <linux/of.h> | ||
| 27 | 28 | ||
| 28 | #include "sdhci-pltfm.h" | 29 | #include "sdhci-pltfm.h" |
| 29 | 30 | ||
| @@ -126,11 +127,18 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev) | |||
| 126 | return sdhci_pltfm_unregister(pdev); | 127 | return sdhci_pltfm_unregister(pdev); |
| 127 | } | 128 | } |
| 128 | 129 | ||
| 130 | static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = { | ||
| 131 | { .compatible = "marvell,dove-sdhci", }, | ||
| 132 | {} | ||
| 133 | }; | ||
| 134 | MODULE_DEVICE_TABLE(of, sdhci_dove_of_match_table); | ||
| 135 | |||
| 129 | static struct platform_driver sdhci_dove_driver = { | 136 | static struct platform_driver sdhci_dove_driver = { |
| 130 | .driver = { | 137 | .driver = { |
| 131 | .name = "sdhci-dove", | 138 | .name = "sdhci-dove", |
| 132 | .owner = THIS_MODULE, | 139 | .owner = THIS_MODULE, |
| 133 | .pm = SDHCI_PLTFM_PMOPS, | 140 | .pm = SDHCI_PLTFM_PMOPS, |
| 141 | .of_match_table = of_match_ptr(sdhci_dove_of_match_table), | ||
| 134 | }, | 142 | }, |
| 135 | .probe = sdhci_dove_probe, | 143 | .probe = sdhci_dove_probe, |
| 136 | .remove = __devexit_p(sdhci_dove_remove), | 144 | .remove = __devexit_p(sdhci_dove_remove), |
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index f8eb1fb0c921..ae5fcbfa1eef 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
| @@ -21,6 +21,32 @@ | |||
| 21 | #include "sdhci-pltfm.h" | 21 | #include "sdhci-pltfm.h" |
| 22 | #include "sdhci-esdhc.h" | 22 | #include "sdhci-esdhc.h" |
| 23 | 23 | ||
| 24 | #define VENDOR_V_22 0x12 | ||
| 25 | static u32 esdhc_readl(struct sdhci_host *host, int reg) | ||
| 26 | { | ||
| 27 | u32 ret; | ||
| 28 | |||
| 29 | ret = in_be32(host->ioaddr + reg); | ||
| 30 | /* | ||
| 31 | * The bit of ADMA flag in eSDHC is not compatible with standard | ||
| 32 | * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is | ||
| 33 | * supported by eSDHC. | ||
| 34 | * And for many FSL eSDHC controller, the reset value of field | ||
| 35 | * SDHCI_CAN_DO_ADMA1 is one, but some of them can't support ADMA, | ||
| 36 | * only these vendor version is greater than 2.2/0x12 support ADMA. | ||
| 37 | * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the | ||
| 38 | * the verdor version number, oxFE is SDHCI_HOST_VERSION. | ||
| 39 | */ | ||
| 40 | if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) { | ||
| 41 | u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); | ||
| 42 | tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; | ||
| 43 | if (tmp > VENDOR_V_22) | ||
| 44 | ret |= SDHCI_CAN_DO_ADMA2; | ||
| 45 | } | ||
| 46 | |||
| 47 | return ret; | ||
| 48 | } | ||
| 49 | |||
| 24 | static u16 esdhc_readw(struct sdhci_host *host, int reg) | 50 | static u16 esdhc_readw(struct sdhci_host *host, int reg) |
| 25 | { | 51 | { |
| 26 | u16 ret; | 52 | u16 ret; |
| @@ -144,7 +170,7 @@ static void esdhc_of_resume(struct sdhci_host *host) | |||
| 144 | #endif | 170 | #endif |
| 145 | 171 | ||
| 146 | static struct sdhci_ops sdhci_esdhc_ops = { | 172 | static struct sdhci_ops sdhci_esdhc_ops = { |
| 147 | .read_l = sdhci_be32bs_readl, | 173 | .read_l = esdhc_readl, |
| 148 | .read_w = esdhc_readw, | 174 | .read_w = esdhc_readw, |
| 149 | .read_b = esdhc_readb, | 175 | .read_b = esdhc_readb, |
| 150 | .write_l = sdhci_be32bs_writel, | 176 | .write_l = sdhci_be32bs_writel, |
| @@ -161,9 +187,13 @@ static struct sdhci_ops sdhci_esdhc_ops = { | |||
| 161 | }; | 187 | }; |
| 162 | 188 | ||
| 163 | static struct sdhci_pltfm_data sdhci_esdhc_pdata = { | 189 | static struct sdhci_pltfm_data sdhci_esdhc_pdata = { |
| 164 | /* card detection could be handled via GPIO */ | 190 | /* |
| 191 | * card detection could be handled via GPIO | ||
| 192 | * eSDHC cannot support End Attribute in NOP ADMA descriptor | ||
| 193 | */ | ||
| 165 | .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION | 194 | .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION |
| 166 | | SDHCI_QUIRK_NO_CARD_NO_RESET, | 195 | | SDHCI_QUIRK_NO_CARD_NO_RESET |
| 196 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | ||
| 167 | .ops = &sdhci_esdhc_ops, | 197 | .ops = &sdhci_esdhc_ops, |
| 168 | }; | 198 | }; |
| 169 | 199 | ||
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 9722d43d6140..4bb74b042a06 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -1476,24 +1476,7 @@ static struct pci_driver sdhci_driver = { | |||
| 1476 | }, | 1476 | }, |
| 1477 | }; | 1477 | }; |
| 1478 | 1478 | ||
| 1479 | /*****************************************************************************\ | 1479 | module_pci_driver(sdhci_driver); |
| 1480 | * * | ||
| 1481 | * Driver init/exit * | ||
| 1482 | * * | ||
| 1483 | \*****************************************************************************/ | ||
| 1484 | |||
| 1485 | static int __init sdhci_drv_init(void) | ||
| 1486 | { | ||
| 1487 | return pci_register_driver(&sdhci_driver); | ||
| 1488 | } | ||
| 1489 | |||
| 1490 | static void __exit sdhci_drv_exit(void) | ||
| 1491 | { | ||
| 1492 | pci_unregister_driver(&sdhci_driver); | ||
| 1493 | } | ||
| 1494 | |||
| 1495 | module_init(sdhci_drv_init); | ||
| 1496 | module_exit(sdhci_drv_exit); | ||
| 1497 | 1480 | ||
| 1498 | MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); | 1481 | MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); |
| 1499 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver"); | 1482 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver"); |
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index d9a4ef4f1ed0..65551a9709cc 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
| @@ -75,6 +75,9 @@ void sdhci_get_of_property(struct platform_device *pdev) | |||
| 75 | if (sdhci_of_wp_inverted(np)) | 75 | if (sdhci_of_wp_inverted(np)) |
| 76 | host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; | 76 | host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; |
| 77 | 77 | ||
| 78 | if (of_get_property(np, "broken-cd", NULL)) | ||
| 79 | host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; | ||
| 80 | |||
| 78 | if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc")) | 81 | if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc")) |
| 79 | host->quirks |= SDHCI_QUIRK_BROKEN_DMA; | 82 | host->quirks |= SDHCI_QUIRK_BROKEN_DMA; |
| 80 | 83 | ||
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index b6ee8857e226..8e63a9c04e31 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c | |||
| @@ -197,7 +197,7 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) | |||
| 197 | goto err_clk_get; | 197 | goto err_clk_get; |
| 198 | } | 198 | } |
| 199 | pltfm_host->clk = clk; | 199 | pltfm_host->clk = clk; |
| 200 | clk_enable(clk); | 200 | clk_prepare_enable(clk); |
| 201 | 201 | ||
| 202 | host->quirks = SDHCI_QUIRK_BROKEN_ADMA | 202 | host->quirks = SDHCI_QUIRK_BROKEN_ADMA |
| 203 | | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 203 | | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
| @@ -239,7 +239,7 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) | |||
| 239 | return 0; | 239 | return 0; |
| 240 | 240 | ||
| 241 | err_add_host: | 241 | err_add_host: |
| 242 | clk_disable(clk); | 242 | clk_disable_unprepare(clk); |
| 243 | clk_put(clk); | 243 | clk_put(clk); |
| 244 | err_clk_get: | 244 | err_clk_get: |
| 245 | sdhci_pltfm_free(pdev); | 245 | sdhci_pltfm_free(pdev); |
| @@ -255,7 +255,7 @@ static int __devexit sdhci_pxav2_remove(struct platform_device *pdev) | |||
| 255 | 255 | ||
| 256 | sdhci_remove_host(host, 1); | 256 | sdhci_remove_host(host, 1); |
| 257 | 257 | ||
| 258 | clk_disable(pltfm_host->clk); | 258 | clk_disable_unprepare(pltfm_host->clk); |
| 259 | clk_put(pltfm_host->clk); | 259 | clk_put(pltfm_host->clk); |
| 260 | sdhci_pltfm_free(pdev); | 260 | sdhci_pltfm_free(pdev); |
| 261 | kfree(pxa); | 261 | kfree(pxa); |
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 07fe3834fe0b..e918a2bb3af1 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c | |||
| @@ -24,12 +24,14 @@ | |||
| 24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
| 25 | #include <linux/mmc/card.h> | 25 | #include <linux/mmc/card.h> |
| 26 | #include <linux/mmc/host.h> | 26 | #include <linux/mmc/host.h> |
| 27 | #include <linux/mmc/slot-gpio.h> | ||
| 27 | #include <linux/platform_data/pxa_sdhci.h> | 28 | #include <linux/platform_data/pxa_sdhci.h> |
| 28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
| 30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 31 | #include <linux/of.h> | 32 | #include <linux/of.h> |
| 32 | #include <linux/of_device.h> | 33 | #include <linux/of_device.h> |
| 34 | #include <linux/of_gpio.h> | ||
| 33 | 35 | ||
| 34 | #include "sdhci.h" | 36 | #include "sdhci.h" |
| 35 | #include "sdhci-pltfm.h" | 37 | #include "sdhci-pltfm.h" |
| @@ -182,6 +184,7 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) | |||
| 182 | struct device_node *np = dev->of_node; | 184 | struct device_node *np = dev->of_node; |
| 183 | u32 bus_width; | 185 | u32 bus_width; |
| 184 | u32 clk_delay_cycles; | 186 | u32 clk_delay_cycles; |
| 187 | enum of_gpio_flags gpio_flags; | ||
| 185 | 188 | ||
| 186 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 189 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
| 187 | if (!pdata) | 190 | if (!pdata) |
| @@ -198,6 +201,10 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) | |||
| 198 | if (clk_delay_cycles > 0) | 201 | if (clk_delay_cycles > 0) |
| 199 | pdata->clk_delay_cycles = clk_delay_cycles; | 202 | pdata->clk_delay_cycles = clk_delay_cycles; |
| 200 | 203 | ||
| 204 | pdata->ext_cd_gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &gpio_flags); | ||
| 205 | if (gpio_flags != OF_GPIO_ACTIVE_LOW) | ||
| 206 | pdata->host_caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; | ||
| 207 | |||
| 201 | return pdata; | 208 | return pdata; |
| 202 | } | 209 | } |
| 203 | #else | 210 | #else |
| @@ -231,14 +238,14 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 231 | pltfm_host = sdhci_priv(host); | 238 | pltfm_host = sdhci_priv(host); |
| 232 | pltfm_host->priv = pxa; | 239 | pltfm_host->priv = pxa; |
| 233 | 240 | ||
| 234 | clk = clk_get(dev, "PXA-SDHCLK"); | 241 | clk = clk_get(dev, NULL); |
| 235 | if (IS_ERR(clk)) { | 242 | if (IS_ERR(clk)) { |
| 236 | dev_err(dev, "failed to get io clock\n"); | 243 | dev_err(dev, "failed to get io clock\n"); |
| 237 | ret = PTR_ERR(clk); | 244 | ret = PTR_ERR(clk); |
| 238 | goto err_clk_get; | 245 | goto err_clk_get; |
| 239 | } | 246 | } |
| 240 | pltfm_host->clk = clk; | 247 | pltfm_host->clk = clk; |
| 241 | clk_enable(clk); | 248 | clk_prepare_enable(clk); |
| 242 | 249 | ||
| 243 | host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 250 | host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
| 244 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | 251 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
| @@ -266,12 +273,25 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 266 | host->quirks |= pdata->quirks; | 273 | host->quirks |= pdata->quirks; |
| 267 | if (pdata->host_caps) | 274 | if (pdata->host_caps) |
| 268 | host->mmc->caps |= pdata->host_caps; | 275 | host->mmc->caps |= pdata->host_caps; |
| 276 | if (pdata->host_caps2) | ||
| 277 | host->mmc->caps2 |= pdata->host_caps2; | ||
| 269 | if (pdata->pm_caps) | 278 | if (pdata->pm_caps) |
| 270 | host->mmc->pm_caps |= pdata->pm_caps; | 279 | host->mmc->pm_caps |= pdata->pm_caps; |
| 280 | |||
| 281 | if (gpio_is_valid(pdata->ext_cd_gpio)) { | ||
| 282 | ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio); | ||
| 283 | if (ret) { | ||
| 284 | dev_err(mmc_dev(host->mmc), | ||
| 285 | "failed to allocate card detect gpio\n"); | ||
| 286 | goto err_cd_req; | ||
| 287 | } | ||
| 288 | } | ||
| 271 | } | 289 | } |
| 272 | 290 | ||
| 273 | host->ops = &pxav3_sdhci_ops; | 291 | host->ops = &pxav3_sdhci_ops; |
| 274 | 292 | ||
| 293 | sdhci_get_of_property(pdev); | ||
| 294 | |||
| 275 | ret = sdhci_add_host(host); | 295 | ret = sdhci_add_host(host); |
| 276 | if (ret) { | 296 | if (ret) { |
| 277 | dev_err(&pdev->dev, "failed to add host\n"); | 297 | dev_err(&pdev->dev, "failed to add host\n"); |
| @@ -283,8 +303,10 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 283 | return 0; | 303 | return 0; |
| 284 | 304 | ||
| 285 | err_add_host: | 305 | err_add_host: |
| 286 | clk_disable(clk); | 306 | clk_disable_unprepare(clk); |
| 287 | clk_put(clk); | 307 | clk_put(clk); |
| 308 | mmc_gpio_free_cd(host->mmc); | ||
| 309 | err_cd_req: | ||
| 288 | err_clk_get: | 310 | err_clk_get: |
| 289 | sdhci_pltfm_free(pdev); | 311 | sdhci_pltfm_free(pdev); |
| 290 | kfree(pxa); | 312 | kfree(pxa); |
| @@ -296,11 +318,16 @@ static int __devexit sdhci_pxav3_remove(struct platform_device *pdev) | |||
| 296 | struct sdhci_host *host = platform_get_drvdata(pdev); | 318 | struct sdhci_host *host = platform_get_drvdata(pdev); |
| 297 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 319 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 298 | struct sdhci_pxa *pxa = pltfm_host->priv; | 320 | struct sdhci_pxa *pxa = pltfm_host->priv; |
| 321 | struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; | ||
| 299 | 322 | ||
| 300 | sdhci_remove_host(host, 1); | 323 | sdhci_remove_host(host, 1); |
| 301 | 324 | ||
| 302 | clk_disable(pltfm_host->clk); | 325 | clk_disable_unprepare(pltfm_host->clk); |
| 303 | clk_put(pltfm_host->clk); | 326 | clk_put(pltfm_host->clk); |
| 327 | |||
| 328 | if (gpio_is_valid(pdata->ext_cd_gpio)) | ||
| 329 | mmc_gpio_free_cd(host->mmc); | ||
| 330 | |||
| 304 | sdhci_pltfm_free(pdev); | 331 | sdhci_pltfm_free(pdev); |
| 305 | kfree(pxa); | 332 | kfree(pxa); |
| 306 | 333 | ||
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index a50c205ea208..2903949594c6 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
| @@ -34,6 +34,9 @@ | |||
| 34 | 34 | ||
| 35 | #define MAX_BUS_CLK (4) | 35 | #define MAX_BUS_CLK (4) |
| 36 | 36 | ||
| 37 | /* Number of gpio's used is max data bus width + command and clock lines */ | ||
| 38 | #define NUM_GPIOS(x) (x + 2) | ||
| 39 | |||
| 37 | /** | 40 | /** |
| 38 | * struct sdhci_s3c - S3C SDHCI instance | 41 | * struct sdhci_s3c - S3C SDHCI instance |
| 39 | * @host: The SDHCI host created | 42 | * @host: The SDHCI host created |
| @@ -41,6 +44,7 @@ | |||
| 41 | * @ioarea: The resource created when we claimed the IO area. | 44 | * @ioarea: The resource created when we claimed the IO area. |
| 42 | * @pdata: The platform data for this controller. | 45 | * @pdata: The platform data for this controller. |
| 43 | * @cur_clk: The index of the current bus clock. | 46 | * @cur_clk: The index of the current bus clock. |
| 47 | * @gpios: List of gpio numbers parsed from device tree. | ||
| 44 | * @clk_io: The clock for the internal bus interface. | 48 | * @clk_io: The clock for the internal bus interface. |
| 45 | * @clk_bus: The clocks that are available for the SD/MMC bus clock. | 49 | * @clk_bus: The clocks that are available for the SD/MMC bus clock. |
| 46 | */ | 50 | */ |
| @@ -52,6 +56,7 @@ struct sdhci_s3c { | |||
| 52 | unsigned int cur_clk; | 56 | unsigned int cur_clk; |
| 53 | int ext_cd_irq; | 57 | int ext_cd_irq; |
| 54 | int ext_cd_gpio; | 58 | int ext_cd_gpio; |
| 59 | int *gpios; | ||
| 55 | 60 | ||
| 56 | struct clk *clk_io; | 61 | struct clk *clk_io; |
| 57 | struct clk *clk_bus[MAX_BUS_CLK]; | 62 | struct clk *clk_bus[MAX_BUS_CLK]; |
| @@ -166,7 +171,7 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, | |||
| 166 | dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n", | 171 | dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n", |
| 167 | src, rate, wanted, rate / div); | 172 | src, rate, wanted, rate / div); |
| 168 | 173 | ||
| 169 | return (wanted - (rate / div)); | 174 | return wanted - (rate / div); |
| 170 | } | 175 | } |
| 171 | 176 | ||
| 172 | /** | 177 | /** |
| @@ -203,10 +208,12 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 203 | best_src, clock, best); | 208 | best_src, clock, best); |
| 204 | 209 | ||
| 205 | /* select the new clock source */ | 210 | /* select the new clock source */ |
| 206 | |||
| 207 | if (ourhost->cur_clk != best_src) { | 211 | if (ourhost->cur_clk != best_src) { |
| 208 | struct clk *clk = ourhost->clk_bus[best_src]; | 212 | struct clk *clk = ourhost->clk_bus[best_src]; |
| 209 | 213 | ||
| 214 | clk_enable(clk); | ||
| 215 | clk_disable(ourhost->clk_bus[ourhost->cur_clk]); | ||
| 216 | |||
| 210 | /* turn clock off to card before changing clock source */ | 217 | /* turn clock off to card before changing clock source */ |
| 211 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); | 218 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); |
| 212 | 219 | ||
| @@ -288,6 +295,7 @@ static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host) | |||
| 288 | static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) | 295 | static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) |
| 289 | { | 296 | { |
| 290 | struct sdhci_s3c *ourhost = to_s3c(host); | 297 | struct sdhci_s3c *ourhost = to_s3c(host); |
| 298 | struct device *dev = &ourhost->pdev->dev; | ||
| 291 | unsigned long timeout; | 299 | unsigned long timeout; |
| 292 | u16 clk = 0; | 300 | u16 clk = 0; |
| 293 | 301 | ||
| @@ -309,8 +317,8 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 309 | while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) | 317 | while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) |
| 310 | & SDHCI_CLOCK_INT_STABLE)) { | 318 | & SDHCI_CLOCK_INT_STABLE)) { |
| 311 | if (timeout == 0) { | 319 | if (timeout == 0) { |
| 312 | printk(KERN_ERR "%s: Internal clock never " | 320 | dev_err(dev, "%s: Internal clock never stabilised.\n", |
| 313 | "stabilised.\n", mmc_hostname(host->mmc)); | 321 | mmc_hostname(host->mmc)); |
| 314 | return; | 322 | return; |
| 315 | } | 323 | } |
| 316 | timeout--; | 324 | timeout--; |
| @@ -404,7 +412,9 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc) | |||
| 404 | if (sc->ext_cd_irq && | 412 | if (sc->ext_cd_irq && |
| 405 | request_threaded_irq(sc->ext_cd_irq, NULL, | 413 | request_threaded_irq(sc->ext_cd_irq, NULL, |
| 406 | sdhci_s3c_gpio_card_detect_thread, | 414 | sdhci_s3c_gpio_card_detect_thread, |
| 407 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 415 | IRQF_TRIGGER_RISING | |
| 416 | IRQF_TRIGGER_FALLING | | ||
| 417 | IRQF_ONESHOT, | ||
| 408 | dev_name(dev), sc) == 0) { | 418 | dev_name(dev), sc) == 0) { |
| 409 | int status = gpio_get_value(sc->ext_cd_gpio); | 419 | int status = gpio_get_value(sc->ext_cd_gpio); |
| 410 | if (pdata->ext_cd_gpio_invert) | 420 | if (pdata->ext_cd_gpio_invert) |
| @@ -419,9 +429,121 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc) | |||
| 419 | } | 429 | } |
| 420 | } | 430 | } |
| 421 | 431 | ||
| 432 | #ifdef CONFIG_OF | ||
| 433 | static int __devinit sdhci_s3c_parse_dt(struct device *dev, | ||
| 434 | struct sdhci_host *host, struct s3c_sdhci_platdata *pdata) | ||
| 435 | { | ||
| 436 | struct device_node *node = dev->of_node; | ||
| 437 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
| 438 | u32 max_width; | ||
| 439 | int gpio, cnt, ret; | ||
| 440 | |||
| 441 | /* if the bus-width property is not specified, assume width as 1 */ | ||
| 442 | if (of_property_read_u32(node, "bus-width", &max_width)) | ||
| 443 | max_width = 1; | ||
| 444 | pdata->max_width = max_width; | ||
| 445 | |||
| 446 | ourhost->gpios = devm_kzalloc(dev, NUM_GPIOS(pdata->max_width) * | ||
| 447 | sizeof(int), GFP_KERNEL); | ||
| 448 | if (!ourhost->gpios) | ||
| 449 | return -ENOMEM; | ||
| 450 | |||
| 451 | /* get the card detection method */ | ||
| 452 | if (of_get_property(node, "broken-cd", 0)) { | ||
| 453 | pdata->cd_type = S3C_SDHCI_CD_NONE; | ||
| 454 | goto setup_bus; | ||
| 455 | } | ||
| 456 | |||
| 457 | if (of_get_property(node, "non-removable", 0)) { | ||
| 458 | pdata->cd_type = S3C_SDHCI_CD_PERMANENT; | ||
| 459 | goto setup_bus; | ||
| 460 | } | ||
| 461 | |||
| 462 | gpio = of_get_named_gpio(node, "cd-gpios", 0); | ||
| 463 | if (gpio_is_valid(gpio)) { | ||
| 464 | pdata->cd_type = S3C_SDHCI_CD_GPIO; | ||
| 465 | goto found_cd; | ||
| 466 | } else if (gpio != -ENOENT) { | ||
| 467 | dev_err(dev, "invalid card detect gpio specified\n"); | ||
| 468 | return -EINVAL; | ||
| 469 | } | ||
| 470 | |||
| 471 | gpio = of_get_named_gpio(node, "samsung,cd-pinmux-gpio", 0); | ||
| 472 | if (gpio_is_valid(gpio)) { | ||
| 473 | pdata->cd_type = S3C_SDHCI_CD_INTERNAL; | ||
| 474 | goto found_cd; | ||
| 475 | } else if (gpio != -ENOENT) { | ||
| 476 | dev_err(dev, "invalid card detect gpio specified\n"); | ||
| 477 | return -EINVAL; | ||
| 478 | } | ||
| 479 | |||
| 480 | dev_info(dev, "assuming no card detect line available\n"); | ||
| 481 | pdata->cd_type = S3C_SDHCI_CD_NONE; | ||
| 482 | |||
| 483 | found_cd: | ||
| 484 | if (pdata->cd_type == S3C_SDHCI_CD_GPIO) { | ||
| 485 | pdata->ext_cd_gpio = gpio; | ||
| 486 | ourhost->ext_cd_gpio = -1; | ||
| 487 | if (of_get_property(node, "cd-inverted", NULL)) | ||
| 488 | pdata->ext_cd_gpio_invert = 1; | ||
| 489 | } else if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | ||
| 490 | ret = gpio_request(gpio, "sdhci-cd"); | ||
| 491 | if (ret) { | ||
| 492 | dev_err(dev, "card detect gpio request failed\n"); | ||
| 493 | return -EINVAL; | ||
| 494 | } | ||
| 495 | ourhost->ext_cd_gpio = gpio; | ||
| 496 | } | ||
| 497 | |||
| 498 | setup_bus: | ||
| 499 | /* get the gpios for command, clock and data lines */ | ||
| 500 | for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) { | ||
| 501 | gpio = of_get_gpio(node, cnt); | ||
| 502 | if (!gpio_is_valid(gpio)) { | ||
| 503 | dev_err(dev, "invalid gpio[%d]\n", cnt); | ||
| 504 | goto err_free_dt_cd_gpio; | ||
| 505 | } | ||
| 506 | ourhost->gpios[cnt] = gpio; | ||
| 507 | } | ||
| 508 | |||
| 509 | for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) { | ||
| 510 | ret = gpio_request(ourhost->gpios[cnt], "sdhci-gpio"); | ||
| 511 | if (ret) { | ||
| 512 | dev_err(dev, "gpio[%d] request failed\n", cnt); | ||
| 513 | goto err_free_dt_gpios; | ||
| 514 | } | ||
| 515 | } | ||
| 516 | |||
| 517 | return 0; | ||
| 518 | |||
| 519 | err_free_dt_gpios: | ||
| 520 | while (--cnt >= 0) | ||
| 521 | gpio_free(ourhost->gpios[cnt]); | ||
| 522 | err_free_dt_cd_gpio: | ||
| 523 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) | ||
| 524 | gpio_free(ourhost->ext_cd_gpio); | ||
| 525 | return -EINVAL; | ||
| 526 | } | ||
| 527 | #else | ||
| 528 | static int __devinit sdhci_s3c_parse_dt(struct device *dev, | ||
| 529 | struct sdhci_host *host, struct s3c_sdhci_platdata *pdata) | ||
| 530 | { | ||
| 531 | return -EINVAL; | ||
| 532 | } | ||
| 533 | #endif | ||
| 534 | |||
| 535 | static const struct of_device_id sdhci_s3c_dt_match[]; | ||
| 536 | |||
| 422 | static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( | 537 | static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( |
| 423 | struct platform_device *pdev) | 538 | struct platform_device *pdev) |
| 424 | { | 539 | { |
| 540 | #ifdef CONFIG_OF | ||
| 541 | if (pdev->dev.of_node) { | ||
| 542 | const struct of_device_id *match; | ||
| 543 | match = of_match_node(sdhci_s3c_dt_match, pdev->dev.of_node); | ||
| 544 | return (struct sdhci_s3c_drv_data *)match->data; | ||
| 545 | } | ||
| 546 | #endif | ||
| 425 | return (struct sdhci_s3c_drv_data *) | 547 | return (struct sdhci_s3c_drv_data *) |
| 426 | platform_get_device_id(pdev)->driver_data; | 548 | platform_get_device_id(pdev)->driver_data; |
| 427 | } | 549 | } |
| @@ -436,7 +558,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
| 436 | struct resource *res; | 558 | struct resource *res; |
| 437 | int ret, irq, ptr, clks; | 559 | int ret, irq, ptr, clks; |
| 438 | 560 | ||
| 439 | if (!pdev->dev.platform_data) { | 561 | if (!pdev->dev.platform_data && !pdev->dev.of_node) { |
| 440 | dev_err(dev, "no device data specified\n"); | 562 | dev_err(dev, "no device data specified\n"); |
| 441 | return -ENOENT; | 563 | return -ENOENT; |
| 442 | } | 564 | } |
| @@ -452,21 +574,28 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
| 452 | dev_err(dev, "sdhci_alloc_host() failed\n"); | 574 | dev_err(dev, "sdhci_alloc_host() failed\n"); |
| 453 | return PTR_ERR(host); | 575 | return PTR_ERR(host); |
| 454 | } | 576 | } |
| 577 | sc = sdhci_priv(host); | ||
| 455 | 578 | ||
| 456 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 579 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
| 457 | if (!pdata) { | 580 | if (!pdata) { |
| 458 | ret = -ENOMEM; | 581 | ret = -ENOMEM; |
| 459 | goto err_io_clk; | 582 | goto err_pdata; |
| 583 | } | ||
| 584 | |||
| 585 | if (pdev->dev.of_node) { | ||
| 586 | ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata); | ||
| 587 | if (ret) | ||
| 588 | goto err_pdata; | ||
| 589 | } else { | ||
| 590 | memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); | ||
| 591 | sc->ext_cd_gpio = -1; /* invalid gpio number */ | ||
| 460 | } | 592 | } |
| 461 | memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); | ||
| 462 | 593 | ||
| 463 | drv_data = sdhci_s3c_get_driver_data(pdev); | 594 | drv_data = sdhci_s3c_get_driver_data(pdev); |
| 464 | sc = sdhci_priv(host); | ||
| 465 | 595 | ||
| 466 | sc->host = host; | 596 | sc->host = host; |
| 467 | sc->pdev = pdev; | 597 | sc->pdev = pdev; |
| 468 | sc->pdata = pdata; | 598 | sc->pdata = pdata; |
| 469 | sc->ext_cd_gpio = -1; /* invalid gpio number */ | ||
| 470 | 599 | ||
| 471 | platform_set_drvdata(pdev, host); | 600 | platform_set_drvdata(pdev, host); |
| 472 | 601 | ||
| @@ -486,9 +615,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
| 486 | 615 | ||
| 487 | snprintf(name, 14, "mmc_busclk.%d", ptr); | 616 | snprintf(name, 14, "mmc_busclk.%d", ptr); |
| 488 | clk = clk_get(dev, name); | 617 | clk = clk_get(dev, name); |
| 489 | if (IS_ERR(clk)) { | 618 | if (IS_ERR(clk)) |
| 490 | continue; | 619 | continue; |
| 491 | } | ||
| 492 | 620 | ||
| 493 | clks++; | 621 | clks++; |
| 494 | sc->clk_bus[ptr] = clk; | 622 | sc->clk_bus[ptr] = clk; |
| @@ -499,8 +627,6 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
| 499 | */ | 627 | */ |
| 500 | sc->cur_clk = ptr; | 628 | sc->cur_clk = ptr; |
| 501 | 629 | ||
| 502 | clk_enable(clk); | ||
| 503 | |||
| 504 | dev_info(dev, "clock source %d: %s (%ld Hz)\n", | 630 | dev_info(dev, "clock source %d: %s (%ld Hz)\n", |
| 505 | ptr, name, clk_get_rate(clk)); | 631 | ptr, name, clk_get_rate(clk)); |
| 506 | } | 632 | } |
| @@ -511,6 +637,10 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
| 511 | goto err_no_busclks; | 637 | goto err_no_busclks; |
| 512 | } | 638 | } |
| 513 | 639 | ||
| 640 | #ifndef CONFIG_PM_RUNTIME | ||
| 641 | clk_enable(sc->clk_bus[sc->cur_clk]); | ||
| 642 | #endif | ||
| 643 | |||
| 514 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 644 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 515 | host->ioaddr = devm_request_and_ioremap(&pdev->dev, res); | 645 | host->ioaddr = devm_request_and_ioremap(&pdev->dev, res); |
| 516 | if (!host->ioaddr) { | 646 | if (!host->ioaddr) { |
| @@ -616,12 +746,17 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
| 616 | gpio_is_valid(pdata->ext_cd_gpio)) | 746 | gpio_is_valid(pdata->ext_cd_gpio)) |
| 617 | sdhci_s3c_setup_card_detect_gpio(sc); | 747 | sdhci_s3c_setup_card_detect_gpio(sc); |
| 618 | 748 | ||
| 749 | #ifdef CONFIG_PM_RUNTIME | ||
| 750 | clk_disable(sc->clk_io); | ||
| 751 | #endif | ||
| 619 | return 0; | 752 | return 0; |
| 620 | 753 | ||
| 621 | err_req_regs: | 754 | err_req_regs: |
| 755 | #ifndef CONFIG_PM_RUNTIME | ||
| 756 | clk_disable(sc->clk_bus[sc->cur_clk]); | ||
| 757 | #endif | ||
| 622 | for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { | 758 | for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { |
| 623 | if (sc->clk_bus[ptr]) { | 759 | if (sc->clk_bus[ptr]) { |
| 624 | clk_disable(sc->clk_bus[ptr]); | ||
| 625 | clk_put(sc->clk_bus[ptr]); | 760 | clk_put(sc->clk_bus[ptr]); |
| 626 | } | 761 | } |
| 627 | } | 762 | } |
| @@ -631,6 +766,12 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
| 631 | clk_put(sc->clk_io); | 766 | clk_put(sc->clk_io); |
| 632 | 767 | ||
| 633 | err_io_clk: | 768 | err_io_clk: |
| 769 | for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++) | ||
| 770 | gpio_free(sc->gpios[ptr]); | ||
| 771 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) | ||
| 772 | gpio_free(sc->ext_cd_gpio); | ||
| 773 | |||
| 774 | err_pdata: | ||
| 634 | sdhci_free_host(host); | 775 | sdhci_free_host(host); |
| 635 | 776 | ||
| 636 | return ret; | 777 | return ret; |
| @@ -638,9 +779,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
| 638 | 779 | ||
| 639 | static int __devexit sdhci_s3c_remove(struct platform_device *pdev) | 780 | static int __devexit sdhci_s3c_remove(struct platform_device *pdev) |
| 640 | { | 781 | { |
| 641 | struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; | ||
| 642 | struct sdhci_host *host = platform_get_drvdata(pdev); | 782 | struct sdhci_host *host = platform_get_drvdata(pdev); |
| 643 | struct sdhci_s3c *sc = sdhci_priv(host); | 783 | struct sdhci_s3c *sc = sdhci_priv(host); |
| 784 | struct s3c_sdhci_platdata *pdata = sc->pdata; | ||
| 644 | int ptr; | 785 | int ptr; |
| 645 | 786 | ||
| 646 | if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup) | 787 | if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup) |
| @@ -652,19 +793,30 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) | |||
| 652 | if (gpio_is_valid(sc->ext_cd_gpio)) | 793 | if (gpio_is_valid(sc->ext_cd_gpio)) |
| 653 | gpio_free(sc->ext_cd_gpio); | 794 | gpio_free(sc->ext_cd_gpio); |
| 654 | 795 | ||
| 796 | #ifdef CONFIG_PM_RUNTIME | ||
| 797 | clk_enable(sc->clk_io); | ||
| 798 | #endif | ||
| 655 | sdhci_remove_host(host, 1); | 799 | sdhci_remove_host(host, 1); |
| 656 | 800 | ||
| 801 | pm_runtime_dont_use_autosuspend(&pdev->dev); | ||
| 657 | pm_runtime_disable(&pdev->dev); | 802 | pm_runtime_disable(&pdev->dev); |
| 658 | 803 | ||
| 659 | for (ptr = 0; ptr < 3; ptr++) { | 804 | #ifndef CONFIG_PM_RUNTIME |
| 805 | clk_disable(sc->clk_bus[sc->cur_clk]); | ||
| 806 | #endif | ||
| 807 | for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { | ||
| 660 | if (sc->clk_bus[ptr]) { | 808 | if (sc->clk_bus[ptr]) { |
| 661 | clk_disable(sc->clk_bus[ptr]); | ||
| 662 | clk_put(sc->clk_bus[ptr]); | 809 | clk_put(sc->clk_bus[ptr]); |
| 663 | } | 810 | } |
| 664 | } | 811 | } |
| 665 | clk_disable(sc->clk_io); | 812 | clk_disable(sc->clk_io); |
| 666 | clk_put(sc->clk_io); | 813 | clk_put(sc->clk_io); |
| 667 | 814 | ||
| 815 | if (pdev->dev.of_node) { | ||
| 816 | for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++) | ||
| 817 | gpio_free(sc->gpios[ptr]); | ||
| 818 | } | ||
| 819 | |||
| 668 | sdhci_free_host(host); | 820 | sdhci_free_host(host); |
| 669 | platform_set_drvdata(pdev, NULL); | 821 | platform_set_drvdata(pdev, NULL); |
| 670 | 822 | ||
| @@ -691,15 +843,28 @@ static int sdhci_s3c_resume(struct device *dev) | |||
| 691 | static int sdhci_s3c_runtime_suspend(struct device *dev) | 843 | static int sdhci_s3c_runtime_suspend(struct device *dev) |
| 692 | { | 844 | { |
| 693 | struct sdhci_host *host = dev_get_drvdata(dev); | 845 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 846 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
| 847 | struct clk *busclk = ourhost->clk_io; | ||
| 848 | int ret; | ||
| 849 | |||
| 850 | ret = sdhci_runtime_suspend_host(host); | ||
| 694 | 851 | ||
| 695 | return sdhci_runtime_suspend_host(host); | 852 | clk_disable(ourhost->clk_bus[ourhost->cur_clk]); |
| 853 | clk_disable(busclk); | ||
| 854 | return ret; | ||
| 696 | } | 855 | } |
| 697 | 856 | ||
| 698 | static int sdhci_s3c_runtime_resume(struct device *dev) | 857 | static int sdhci_s3c_runtime_resume(struct device *dev) |
| 699 | { | 858 | { |
| 700 | struct sdhci_host *host = dev_get_drvdata(dev); | 859 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 860 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
| 861 | struct clk *busclk = ourhost->clk_io; | ||
| 862 | int ret; | ||
| 701 | 863 | ||
| 702 | return sdhci_runtime_resume_host(host); | 864 | clk_enable(busclk); |
| 865 | clk_enable(ourhost->clk_bus[ourhost->cur_clk]); | ||
| 866 | ret = sdhci_runtime_resume_host(host); | ||
| 867 | return ret; | ||
| 703 | } | 868 | } |
| 704 | #endif | 869 | #endif |
| 705 | 870 | ||
| @@ -737,6 +902,16 @@ static struct platform_device_id sdhci_s3c_driver_ids[] = { | |||
| 737 | }; | 902 | }; |
| 738 | MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids); | 903 | MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids); |
| 739 | 904 | ||
| 905 | #ifdef CONFIG_OF | ||
| 906 | static const struct of_device_id sdhci_s3c_dt_match[] = { | ||
| 907 | { .compatible = "samsung,s3c6410-sdhci", }, | ||
| 908 | { .compatible = "samsung,exynos4210-sdhci", | ||
| 909 | .data = (void *)EXYNOS4_SDHCI_DRV_DATA }, | ||
| 910 | {}, | ||
| 911 | }; | ||
| 912 | MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match); | ||
| 913 | #endif | ||
| 914 | |||
| 740 | static struct platform_driver sdhci_s3c_driver = { | 915 | static struct platform_driver sdhci_s3c_driver = { |
| 741 | .probe = sdhci_s3c_probe, | 916 | .probe = sdhci_s3c_probe, |
| 742 | .remove = __devexit_p(sdhci_s3c_remove), | 917 | .remove = __devexit_p(sdhci_s3c_remove), |
| @@ -744,6 +919,7 @@ static struct platform_driver sdhci_s3c_driver = { | |||
| 744 | .driver = { | 919 | .driver = { |
| 745 | .owner = THIS_MODULE, | 920 | .owner = THIS_MODULE, |
| 746 | .name = "s3c-sdhci", | 921 | .name = "s3c-sdhci", |
| 922 | .of_match_table = of_match_ptr(sdhci_s3c_dt_match), | ||
| 747 | .pm = SDHCI_S3C_PMOPS, | 923 | .pm = SDHCI_S3C_PMOPS, |
| 748 | }, | 924 | }, |
| 749 | }; | 925 | }; |
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index 423da8194cd8..6be89c032deb 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c | |||
| @@ -20,6 +20,8 @@ | |||
| 20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
| 22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
| 23 | #include <linux/of.h> | ||
| 24 | #include <linux/of_gpio.h> | ||
| 23 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 24 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
| 25 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| @@ -68,8 +70,42 @@ static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id) | |||
| 68 | return IRQ_HANDLED; | 70 | return IRQ_HANDLED; |
| 69 | } | 71 | } |
| 70 | 72 | ||
| 73 | #ifdef CONFIG_OF | ||
| 74 | static struct sdhci_plat_data * __devinit | ||
| 75 | sdhci_probe_config_dt(struct platform_device *pdev) | ||
| 76 | { | ||
| 77 | struct device_node *np = pdev->dev.of_node; | ||
| 78 | struct sdhci_plat_data *pdata = NULL; | ||
| 79 | int cd_gpio; | ||
| 80 | |||
| 81 | cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); | ||
| 82 | if (!gpio_is_valid(cd_gpio)) | ||
| 83 | cd_gpio = -1; | ||
| 84 | |||
| 85 | /* If pdata is required */ | ||
| 86 | if (cd_gpio != -1) { | ||
| 87 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
| 88 | if (!pdata) { | ||
| 89 | dev_err(&pdev->dev, "DT: kzalloc failed\n"); | ||
| 90 | return ERR_PTR(-ENOMEM); | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | pdata->card_int_gpio = cd_gpio; | ||
| 95 | |||
| 96 | return pdata; | ||
| 97 | } | ||
| 98 | #else | ||
| 99 | static struct sdhci_plat_data * __devinit | ||
| 100 | sdhci_probe_config_dt(struct platform_device *pdev) | ||
| 101 | { | ||
| 102 | return ERR_PTR(-ENOSYS); | ||
| 103 | } | ||
| 104 | #endif | ||
| 105 | |||
| 71 | static int __devinit sdhci_probe(struct platform_device *pdev) | 106 | static int __devinit sdhci_probe(struct platform_device *pdev) |
| 72 | { | 107 | { |
| 108 | struct device_node *np = pdev->dev.of_node; | ||
| 73 | struct sdhci_host *host; | 109 | struct sdhci_host *host; |
| 74 | struct resource *iomem; | 110 | struct resource *iomem; |
| 75 | struct spear_sdhci *sdhci; | 111 | struct spear_sdhci *sdhci; |
| @@ -104,14 +140,22 @@ static int __devinit sdhci_probe(struct platform_device *pdev) | |||
| 104 | goto err; | 140 | goto err; |
| 105 | } | 141 | } |
| 106 | 142 | ||
| 107 | ret = clk_enable(sdhci->clk); | 143 | ret = clk_prepare_enable(sdhci->clk); |
| 108 | if (ret) { | 144 | if (ret) { |
| 109 | dev_dbg(&pdev->dev, "Error enabling clock\n"); | 145 | dev_dbg(&pdev->dev, "Error enabling clock\n"); |
| 110 | goto put_clk; | 146 | goto put_clk; |
| 111 | } | 147 | } |
| 112 | 148 | ||
| 113 | /* overwrite platform_data */ | 149 | if (np) { |
| 114 | sdhci->data = dev_get_platdata(&pdev->dev); | 150 | sdhci->data = sdhci_probe_config_dt(pdev); |
| 151 | if (IS_ERR(sdhci->data)) { | ||
| 152 | dev_err(&pdev->dev, "DT: Failed to get pdata\n"); | ||
| 153 | return -ENODEV; | ||
| 154 | } | ||
| 155 | } else { | ||
| 156 | sdhci->data = dev_get_platdata(&pdev->dev); | ||
| 157 | } | ||
| 158 | |||
| 115 | pdev->dev.platform_data = sdhci; | 159 | pdev->dev.platform_data = sdhci; |
| 116 | 160 | ||
| 117 | if (pdev->dev.parent) | 161 | if (pdev->dev.parent) |
| @@ -216,7 +260,7 @@ set_drvdata: | |||
| 216 | free_host: | 260 | free_host: |
| 217 | sdhci_free_host(host); | 261 | sdhci_free_host(host); |
| 218 | disable_clk: | 262 | disable_clk: |
| 219 | clk_disable(sdhci->clk); | 263 | clk_disable_unprepare(sdhci->clk); |
| 220 | put_clk: | 264 | put_clk: |
| 221 | clk_put(sdhci->clk); | 265 | clk_put(sdhci->clk); |
| 222 | err: | 266 | err: |
| @@ -238,7 +282,7 @@ static int __devexit sdhci_remove(struct platform_device *pdev) | |||
| 238 | 282 | ||
| 239 | sdhci_remove_host(host, dead); | 283 | sdhci_remove_host(host, dead); |
| 240 | sdhci_free_host(host); | 284 | sdhci_free_host(host); |
| 241 | clk_disable(sdhci->clk); | 285 | clk_disable_unprepare(sdhci->clk); |
| 242 | clk_put(sdhci->clk); | 286 | clk_put(sdhci->clk); |
| 243 | 287 | ||
| 244 | return 0; | 288 | return 0; |
| @@ -253,7 +297,7 @@ static int sdhci_suspend(struct device *dev) | |||
| 253 | 297 | ||
| 254 | ret = sdhci_suspend_host(host); | 298 | ret = sdhci_suspend_host(host); |
| 255 | if (!ret) | 299 | if (!ret) |
| 256 | clk_disable(sdhci->clk); | 300 | clk_disable_unprepare(sdhci->clk); |
| 257 | 301 | ||
| 258 | return ret; | 302 | return ret; |
| 259 | } | 303 | } |
| @@ -264,7 +308,7 @@ static int sdhci_resume(struct device *dev) | |||
| 264 | struct spear_sdhci *sdhci = dev_get_platdata(dev); | 308 | struct spear_sdhci *sdhci = dev_get_platdata(dev); |
| 265 | int ret; | 309 | int ret; |
| 266 | 310 | ||
| 267 | ret = clk_enable(sdhci->clk); | 311 | ret = clk_prepare_enable(sdhci->clk); |
| 268 | if (ret) { | 312 | if (ret) { |
| 269 | dev_dbg(dev, "Resume: Error enabling clock\n"); | 313 | dev_dbg(dev, "Resume: Error enabling clock\n"); |
| 270 | return ret; | 314 | return ret; |
| @@ -276,11 +320,20 @@ static int sdhci_resume(struct device *dev) | |||
| 276 | 320 | ||
| 277 | static SIMPLE_DEV_PM_OPS(sdhci_pm_ops, sdhci_suspend, sdhci_resume); | 321 | static SIMPLE_DEV_PM_OPS(sdhci_pm_ops, sdhci_suspend, sdhci_resume); |
| 278 | 322 | ||
| 323 | #ifdef CONFIG_OF | ||
| 324 | static const struct of_device_id sdhci_spear_id_table[] = { | ||
| 325 | { .compatible = "st,spear300-sdhci" }, | ||
| 326 | {} | ||
| 327 | }; | ||
| 328 | MODULE_DEVICE_TABLE(of, sdhci_spear_id_table); | ||
| 329 | #endif | ||
| 330 | |||
| 279 | static struct platform_driver sdhci_driver = { | 331 | static struct platform_driver sdhci_driver = { |
| 280 | .driver = { | 332 | .driver = { |
| 281 | .name = "sdhci", | 333 | .name = "sdhci", |
| 282 | .owner = THIS_MODULE, | 334 | .owner = THIS_MODULE, |
| 283 | .pm = &sdhci_pm_ops, | 335 | .pm = &sdhci_pm_ops, |
| 336 | .of_match_table = of_match_ptr(sdhci_spear_id_table), | ||
| 284 | }, | 337 | }, |
| 285 | .probe = sdhci_probe, | 338 | .probe = sdhci_probe, |
| 286 | .remove = __devexit_p(sdhci_remove), | 339 | .remove = __devexit_p(sdhci_remove), |
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index d43e7462941f..84e8d0c59ee5 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
| @@ -257,10 +257,9 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev) | |||
| 257 | int rc; | 257 | int rc; |
| 258 | 258 | ||
| 259 | match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); | 259 | match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); |
| 260 | if (match) | 260 | if (!match) |
| 261 | soc_data = match->data; | 261 | return -EINVAL; |
| 262 | else | 262 | soc_data = match->data; |
| 263 | soc_data = &soc_data_tegra20; | ||
| 264 | 263 | ||
| 265 | host = sdhci_pltfm_init(pdev, soc_data->pdata); | 264 | host = sdhci_pltfm_init(pdev, soc_data->pdata); |
| 266 | if (IS_ERR(host)) | 265 | if (IS_ERR(host)) |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9a11dc39921c..7922adb42386 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/mmc/mmc.h> | 28 | #include <linux/mmc/mmc.h> |
| 29 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
| 30 | #include <linux/mmc/card.h> | 30 | #include <linux/mmc/card.h> |
| 31 | #include <linux/mmc/slot-gpio.h> | ||
| 31 | 32 | ||
| 32 | #include "sdhci.h" | 33 | #include "sdhci.h" |
| 33 | 34 | ||
| @@ -1293,6 +1294,13 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 1293 | present = sdhci_readl(host, SDHCI_PRESENT_STATE) & | 1294 | present = sdhci_readl(host, SDHCI_PRESENT_STATE) & |
| 1294 | SDHCI_CARD_PRESENT; | 1295 | SDHCI_CARD_PRESENT; |
| 1295 | 1296 | ||
| 1297 | /* If we're using a cd-gpio, testing the presence bit might fail. */ | ||
| 1298 | if (!present) { | ||
| 1299 | int ret = mmc_gpio_get_cd(host->mmc); | ||
| 1300 | if (ret > 0) | ||
| 1301 | present = true; | ||
| 1302 | } | ||
| 1303 | |||
| 1296 | if (!present || host->flags & SDHCI_DEVICE_DEAD) { | 1304 | if (!present || host->flags & SDHCI_DEVICE_DEAD) { |
| 1297 | host->mrq->cmd->error = -ENOMEDIUM; | 1305 | host->mrq->cmd->error = -ENOMEDIUM; |
| 1298 | tasklet_schedule(&host->finish_tasklet); | 1306 | tasklet_schedule(&host->finish_tasklet); |
| @@ -1597,57 +1605,65 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
| 1597 | spin_unlock_irqrestore(&host->lock, flags); | 1605 | spin_unlock_irqrestore(&host->lock, flags); |
| 1598 | } | 1606 | } |
| 1599 | 1607 | ||
| 1600 | static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, | 1608 | static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host, |
| 1601 | struct mmc_ios *ios) | 1609 | u16 ctrl) |
| 1602 | { | 1610 | { |
| 1603 | u8 pwr; | 1611 | int ret; |
| 1604 | u16 clk, ctrl; | ||
| 1605 | u32 present_state; | ||
| 1606 | 1612 | ||
| 1607 | /* | 1613 | /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ |
| 1608 | * Signal Voltage Switching is only applicable for Host Controllers | 1614 | ctrl &= ~SDHCI_CTRL_VDD_180; |
| 1609 | * v3.00 and above. | 1615 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
| 1610 | */ | ||
| 1611 | if (host->version < SDHCI_SPEC_300) | ||
| 1612 | return 0; | ||
| 1613 | 1616 | ||
| 1614 | /* | 1617 | if (host->vqmmc) { |
| 1615 | * We first check whether the request is to set signalling voltage | 1618 | ret = regulator_set_voltage(host->vqmmc, 3300000, 3300000); |
| 1616 | * to 3.3V. If so, we change the voltage to 3.3V and return quickly. | 1619 | if (ret) { |
| 1617 | */ | 1620 | pr_warning("%s: Switching to 3.3V signalling voltage " |
| 1621 | " failed\n", mmc_hostname(host->mmc)); | ||
| 1622 | return -EIO; | ||
| 1623 | } | ||
| 1624 | } | ||
| 1625 | /* Wait for 5ms */ | ||
| 1626 | usleep_range(5000, 5500); | ||
| 1627 | |||
| 1628 | /* 3.3V regulator output should be stable within 5 ms */ | ||
| 1618 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1629 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
| 1619 | if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { | 1630 | if (!(ctrl & SDHCI_CTRL_VDD_180)) |
| 1620 | /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ | 1631 | return 0; |
| 1621 | ctrl &= ~SDHCI_CTRL_VDD_180; | ||
| 1622 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
| 1623 | 1632 | ||
| 1624 | /* Wait for 5ms */ | 1633 | pr_warning("%s: 3.3V regulator output did not became stable\n", |
| 1625 | usleep_range(5000, 5500); | 1634 | mmc_hostname(host->mmc)); |
| 1626 | 1635 | ||
| 1627 | /* 3.3V regulator output should be stable within 5 ms */ | 1636 | return -EIO; |
| 1628 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1637 | } |
| 1629 | if (!(ctrl & SDHCI_CTRL_VDD_180)) | ||
| 1630 | return 0; | ||
| 1631 | else { | ||
| 1632 | pr_info(DRIVER_NAME ": Switching to 3.3V " | ||
| 1633 | "signalling voltage failed\n"); | ||
| 1634 | return -EIO; | ||
| 1635 | } | ||
| 1636 | } else if (!(ctrl & SDHCI_CTRL_VDD_180) && | ||
| 1637 | (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) { | ||
| 1638 | /* Stop SDCLK */ | ||
| 1639 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | ||
| 1640 | clk &= ~SDHCI_CLOCK_CARD_EN; | ||
| 1641 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | ||
| 1642 | 1638 | ||
| 1643 | /* Check whether DAT[3:0] is 0000 */ | 1639 | static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host, |
| 1644 | present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); | 1640 | u16 ctrl) |
| 1645 | if (!((present_state & SDHCI_DATA_LVL_MASK) >> | 1641 | { |
| 1646 | SDHCI_DATA_LVL_SHIFT)) { | 1642 | u8 pwr; |
| 1647 | /* | 1643 | u16 clk; |
| 1648 | * Enable 1.8V Signal Enable in the Host Control2 | 1644 | u32 present_state; |
| 1649 | * register | 1645 | int ret; |
| 1650 | */ | 1646 | |
| 1647 | /* Stop SDCLK */ | ||
| 1648 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | ||
| 1649 | clk &= ~SDHCI_CLOCK_CARD_EN; | ||
| 1650 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | ||
| 1651 | |||
| 1652 | /* Check whether DAT[3:0] is 0000 */ | ||
| 1653 | present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); | ||
| 1654 | if (!((present_state & SDHCI_DATA_LVL_MASK) >> | ||
| 1655 | SDHCI_DATA_LVL_SHIFT)) { | ||
| 1656 | /* | ||
| 1657 | * Enable 1.8V Signal Enable in the Host Control2 | ||
| 1658 | * register | ||
| 1659 | */ | ||
| 1660 | if (host->vqmmc) | ||
| 1661 | ret = regulator_set_voltage(host->vqmmc, | ||
| 1662 | 1800000, 1800000); | ||
| 1663 | else | ||
| 1664 | ret = 0; | ||
| 1665 | |||
| 1666 | if (!ret) { | ||
| 1651 | ctrl |= SDHCI_CTRL_VDD_180; | 1667 | ctrl |= SDHCI_CTRL_VDD_180; |
| 1652 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | 1668 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
| 1653 | 1669 | ||
| @@ -1656,7 +1672,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, | |||
| 1656 | 1672 | ||
| 1657 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1673 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
| 1658 | if (ctrl & SDHCI_CTRL_VDD_180) { | 1674 | if (ctrl & SDHCI_CTRL_VDD_180) { |
| 1659 | /* Provide SDCLK again and wait for 1ms*/ | 1675 | /* Provide SDCLK again and wait for 1ms */ |
| 1660 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | 1676 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); |
| 1661 | clk |= SDHCI_CLOCK_CARD_EN; | 1677 | clk |= SDHCI_CLOCK_CARD_EN; |
| 1662 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | 1678 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); |
| @@ -1673,29 +1689,55 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, | |||
| 1673 | return 0; | 1689 | return 0; |
| 1674 | } | 1690 | } |
| 1675 | } | 1691 | } |
| 1692 | } | ||
| 1676 | 1693 | ||
| 1677 | /* | 1694 | /* |
| 1678 | * If we are here, that means the switch to 1.8V signaling | 1695 | * If we are here, that means the switch to 1.8V signaling |
| 1679 | * failed. We power cycle the card, and retry initialization | 1696 | * failed. We power cycle the card, and retry initialization |
| 1680 | * sequence by setting S18R to 0. | 1697 | * sequence by setting S18R to 0. |
| 1681 | */ | 1698 | */ |
| 1682 | pwr = sdhci_readb(host, SDHCI_POWER_CONTROL); | 1699 | pwr = sdhci_readb(host, SDHCI_POWER_CONTROL); |
| 1683 | pwr &= ~SDHCI_POWER_ON; | 1700 | pwr &= ~SDHCI_POWER_ON; |
| 1684 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | 1701 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); |
| 1685 | if (host->vmmc) | 1702 | if (host->vmmc) |
| 1686 | regulator_disable(host->vmmc); | 1703 | regulator_disable(host->vmmc); |
| 1687 | 1704 | ||
| 1688 | /* Wait for 1ms as per the spec */ | 1705 | /* Wait for 1ms as per the spec */ |
| 1689 | usleep_range(1000, 1500); | 1706 | usleep_range(1000, 1500); |
| 1690 | pwr |= SDHCI_POWER_ON; | 1707 | pwr |= SDHCI_POWER_ON; |
| 1691 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | 1708 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); |
| 1692 | if (host->vmmc) | 1709 | if (host->vmmc) |
| 1693 | regulator_enable(host->vmmc); | 1710 | regulator_enable(host->vmmc); |
| 1694 | 1711 | ||
| 1695 | pr_info(DRIVER_NAME ": Switching to 1.8V signalling " | 1712 | pr_warning("%s: Switching to 1.8V signalling voltage failed, " |
| 1696 | "voltage failed, retrying with S18R set to 0\n"); | 1713 | "retrying with S18R set to 0\n", mmc_hostname(host->mmc)); |
| 1697 | return -EAGAIN; | 1714 | |
| 1698 | } else | 1715 | return -EAGAIN; |
| 1716 | } | ||
| 1717 | |||
| 1718 | static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, | ||
| 1719 | struct mmc_ios *ios) | ||
| 1720 | { | ||
| 1721 | u16 ctrl; | ||
| 1722 | |||
| 1723 | /* | ||
| 1724 | * Signal Voltage Switching is only applicable for Host Controllers | ||
| 1725 | * v3.00 and above. | ||
| 1726 | */ | ||
| 1727 | if (host->version < SDHCI_SPEC_300) | ||
| 1728 | return 0; | ||
| 1729 | |||
| 1730 | /* | ||
| 1731 | * We first check whether the request is to set signalling voltage | ||
| 1732 | * to 3.3V. If so, we change the voltage to 3.3V and return quickly. | ||
| 1733 | */ | ||
| 1734 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
| 1735 | if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) | ||
| 1736 | return sdhci_do_3_3v_signal_voltage_switch(host, ctrl); | ||
| 1737 | else if (!(ctrl & SDHCI_CTRL_VDD_180) && | ||
| 1738 | (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) | ||
| 1739 | return sdhci_do_1_8v_signal_voltage_switch(host, ctrl); | ||
| 1740 | else | ||
| 1699 | /* No signal voltage switch required */ | 1741 | /* No signal voltage switch required */ |
| 1700 | return 0; | 1742 | return 0; |
| 1701 | } | 1743 | } |
| @@ -2802,6 +2844,18 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 2802 | !(host->mmc->caps & MMC_CAP_NONREMOVABLE)) | 2844 | !(host->mmc->caps & MMC_CAP_NONREMOVABLE)) |
| 2803 | mmc->caps |= MMC_CAP_NEEDS_POLL; | 2845 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
| 2804 | 2846 | ||
| 2847 | /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ | ||
| 2848 | host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc"); | ||
| 2849 | if (IS_ERR(host->vqmmc)) { | ||
| 2850 | pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc)); | ||
| 2851 | host->vqmmc = NULL; | ||
| 2852 | } | ||
| 2853 | else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000)) | ||
| 2854 | regulator_enable(host->vqmmc); | ||
| 2855 | else | ||
| 2856 | caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | | ||
| 2857 | SDHCI_SUPPORT_DDR50); | ||
| 2858 | |||
| 2805 | /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ | 2859 | /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ |
| 2806 | if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | | 2860 | if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | |
| 2807 | SDHCI_SUPPORT_DDR50)) | 2861 | SDHCI_SUPPORT_DDR50)) |
| @@ -2832,15 +2886,6 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 2832 | if (caps[1] & SDHCI_DRIVER_TYPE_D) | 2886 | if (caps[1] & SDHCI_DRIVER_TYPE_D) |
| 2833 | mmc->caps |= MMC_CAP_DRIVER_TYPE_D; | 2887 | mmc->caps |= MMC_CAP_DRIVER_TYPE_D; |
| 2834 | 2888 | ||
| 2835 | /* | ||
| 2836 | * If Power Off Notify capability is enabled by the host, | ||
| 2837 | * set notify to short power off notify timeout value. | ||
| 2838 | */ | ||
| 2839 | if (mmc->caps2 & MMC_CAP2_POWEROFF_NOTIFY) | ||
| 2840 | mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT; | ||
| 2841 | else | ||
| 2842 | mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE; | ||
| 2843 | |||
| 2844 | /* Initial value for re-tuning timer count */ | 2889 | /* Initial value for re-tuning timer count */ |
| 2845 | host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >> | 2890 | host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >> |
| 2846 | SDHCI_RETUNING_TIMER_COUNT_SHIFT; | 2891 | SDHCI_RETUNING_TIMER_COUNT_SHIFT; |
| @@ -2862,7 +2907,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 2862 | if (IS_ERR(host->vmmc)) { | 2907 | if (IS_ERR(host->vmmc)) { |
| 2863 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); | 2908 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); |
| 2864 | host->vmmc = NULL; | 2909 | host->vmmc = NULL; |
| 2865 | } | 2910 | } else |
| 2911 | regulator_enable(host->vmmc); | ||
| 2866 | 2912 | ||
| 2867 | #ifdef CONFIG_REGULATOR | 2913 | #ifdef CONFIG_REGULATOR |
| 2868 | if (host->vmmc) { | 2914 | if (host->vmmc) { |
| @@ -3119,8 +3165,15 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) | |||
| 3119 | tasklet_kill(&host->card_tasklet); | 3165 | tasklet_kill(&host->card_tasklet); |
| 3120 | tasklet_kill(&host->finish_tasklet); | 3166 | tasklet_kill(&host->finish_tasklet); |
| 3121 | 3167 | ||
| 3122 | if (host->vmmc) | 3168 | if (host->vmmc) { |
| 3169 | regulator_disable(host->vmmc); | ||
| 3123 | regulator_put(host->vmmc); | 3170 | regulator_put(host->vmmc); |
| 3171 | } | ||
| 3172 | |||
| 3173 | if (host->vqmmc) { | ||
| 3174 | regulator_disable(host->vqmmc); | ||
| 3175 | regulator_put(host->vqmmc); | ||
| 3176 | } | ||
| 3124 | 3177 | ||
| 3125 | kfree(host->adma_desc); | 3178 | kfree(host->adma_desc); |
| 3126 | kfree(host->align_buffer); | 3179 | kfree(host->align_buffer); |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 5d8142773fac..11d2bc3b51d5 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
| @@ -1213,7 +1213,9 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | |||
| 1213 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFRE); | 1213 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFRE); |
| 1214 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); | 1214 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); |
| 1215 | } else if (state & INT_DTRANE) { | 1215 | } else if (state & INT_DTRANE) { |
| 1216 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_DTRANE); | 1216 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, |
| 1217 | ~(INT_CMD12DRE | INT_CMD12RBE | | ||
| 1218 | INT_CMD12CRE | INT_DTRANE)); | ||
| 1217 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); | 1219 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); |
| 1218 | } else if (state & INT_CMD12RBE) { | 1220 | } else if (state & INT_CMD12RBE) { |
| 1219 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, | 1221 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, |
| @@ -1229,6 +1231,10 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | |||
| 1229 | host->sd_error = true; | 1231 | host->sd_error = true; |
| 1230 | dev_dbg(&host->pd->dev, "int err state = %08x\n", state); | 1232 | dev_dbg(&host->pd->dev, "int err state = %08x\n", state); |
| 1231 | } | 1233 | } |
| 1234 | if (host->state == STATE_IDLE) { | ||
| 1235 | dev_info(&host->pd->dev, "Spurious IRQ status 0x%x", state); | ||
| 1236 | return IRQ_HANDLED; | ||
| 1237 | } | ||
| 1232 | if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) { | 1238 | if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) { |
| 1233 | if (!host->dma_active) | 1239 | if (!host->dma_active) |
| 1234 | return IRQ_WAKE_THREAD; | 1240 | return IRQ_WAKE_THREAD; |
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 4b83c43f950d..f18becef156d 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c | |||
| @@ -1337,21 +1337,7 @@ static struct pci_driver via_sd_driver = { | |||
| 1337 | .resume = via_sd_resume, | 1337 | .resume = via_sd_resume, |
| 1338 | }; | 1338 | }; |
| 1339 | 1339 | ||
| 1340 | static int __init via_sd_drv_init(void) | 1340 | module_pci_driver(via_sd_driver); |
| 1341 | { | ||
| 1342 | pr_info(DRV_NAME ": VIA SD/MMC Card Reader driver " | ||
| 1343 | "(C) 2008 VIA Technologies, Inc.\n"); | ||
| 1344 | |||
| 1345 | return pci_register_driver(&via_sd_driver); | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | static void __exit via_sd_drv_exit(void) | ||
| 1349 | { | ||
| 1350 | pci_unregister_driver(&via_sd_driver); | ||
| 1351 | } | ||
| 1352 | |||
| 1353 | module_init(via_sd_drv_init); | ||
| 1354 | module_exit(via_sd_drv_exit); | ||
| 1355 | 1341 | ||
| 1356 | MODULE_LICENSE("GPL"); | 1342 | MODULE_LICENSE("GPL"); |
| 1357 | MODULE_AUTHOR("VIA Technologies Inc."); | 1343 | MODULE_AUTHOR("VIA Technologies Inc."); |
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index 58eab9ac1d01..d5655a63eda4 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c | |||
| @@ -2358,9 +2358,9 @@ error5: | |||
| 2358 | * which is contained at the end of struct mmc | 2358 | * which is contained at the end of struct mmc |
| 2359 | */ | 2359 | */ |
| 2360 | error4: | 2360 | error4: |
| 2361 | usb_free_urb(command_out_urb); | ||
| 2362 | error1: | ||
| 2363 | usb_free_urb(command_res_urb); | 2361 | usb_free_urb(command_res_urb); |
| 2362 | error1: | ||
| 2363 | usb_free_urb(command_out_urb); | ||
| 2364 | error0: | 2364 | error0: |
| 2365 | return retval; | 2365 | return retval; |
| 2366 | } | 2366 | } |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 4b27f9f503e4..943550dfe9ea 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
| @@ -57,6 +57,7 @@ struct mmc_ext_csd { | |||
| 57 | unsigned int sa_timeout; /* Units: 100ns */ | 57 | unsigned int sa_timeout; /* Units: 100ns */ |
| 58 | unsigned int generic_cmd6_time; /* Units: 10ms */ | 58 | unsigned int generic_cmd6_time; /* Units: 10ms */ |
| 59 | unsigned int power_off_longtime; /* Units: ms */ | 59 | unsigned int power_off_longtime; /* Units: ms */ |
| 60 | u8 power_off_notification; /* state */ | ||
| 60 | unsigned int hs_max_dtr; | 61 | unsigned int hs_max_dtr; |
| 61 | #define MMC_HIGH_26_MAX_DTR 26000000 | 62 | #define MMC_HIGH_26_MAX_DTR 26000000 |
| 62 | #define MMC_HIGH_52_MAX_DTR 52000000 | 63 | #define MMC_HIGH_52_MAX_DTR 52000000 |
| @@ -76,10 +77,13 @@ struct mmc_ext_csd { | |||
| 76 | bool hpi_en; /* HPI enablebit */ | 77 | bool hpi_en; /* HPI enablebit */ |
| 77 | bool hpi; /* HPI support bit */ | 78 | bool hpi; /* HPI support bit */ |
| 78 | unsigned int hpi_cmd; /* cmd used as HPI */ | 79 | unsigned int hpi_cmd; /* cmd used as HPI */ |
| 80 | bool bkops; /* background support bit */ | ||
| 81 | bool bkops_en; /* background enable bit */ | ||
| 79 | unsigned int data_sector_size; /* 512 bytes or 4KB */ | 82 | unsigned int data_sector_size; /* 512 bytes or 4KB */ |
| 80 | unsigned int data_tag_unit_size; /* DATA TAG UNIT size */ | 83 | unsigned int data_tag_unit_size; /* DATA TAG UNIT size */ |
| 81 | unsigned int boot_ro_lock; /* ro lock support */ | 84 | unsigned int boot_ro_lock; /* ro lock support */ |
| 82 | bool boot_ro_lockable; | 85 | bool boot_ro_lockable; |
| 86 | u8 raw_exception_status; /* 53 */ | ||
| 83 | u8 raw_partition_support; /* 160 */ | 87 | u8 raw_partition_support; /* 160 */ |
| 84 | u8 raw_erased_mem_count; /* 181 */ | 88 | u8 raw_erased_mem_count; /* 181 */ |
| 85 | u8 raw_ext_csd_structure; /* 194 */ | 89 | u8 raw_ext_csd_structure; /* 194 */ |
| @@ -93,6 +97,7 @@ struct mmc_ext_csd { | |||
| 93 | u8 raw_sec_erase_mult; /* 230 */ | 97 | u8 raw_sec_erase_mult; /* 230 */ |
| 94 | u8 raw_sec_feature_support;/* 231 */ | 98 | u8 raw_sec_feature_support;/* 231 */ |
| 95 | u8 raw_trim_mult; /* 232 */ | 99 | u8 raw_trim_mult; /* 232 */ |
| 100 | u8 raw_bkops_status; /* 246 */ | ||
| 96 | u8 raw_sectors[4]; /* 212 - 4 bytes */ | 101 | u8 raw_sectors[4]; /* 212 - 4 bytes */ |
| 97 | 102 | ||
| 98 | unsigned int feature_support; | 103 | unsigned int feature_support; |
| @@ -225,7 +230,7 @@ struct mmc_card { | |||
| 225 | #define MMC_CARD_SDXC (1<<6) /* card is SDXC */ | 230 | #define MMC_CARD_SDXC (1<<6) /* card is SDXC */ |
| 226 | #define MMC_CARD_REMOVED (1<<7) /* card has been removed */ | 231 | #define MMC_CARD_REMOVED (1<<7) /* card has been removed */ |
| 227 | #define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */ | 232 | #define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */ |
| 228 | #define MMC_STATE_SLEEP (1<<9) /* card is in sleep state */ | 233 | #define MMC_STATE_DOING_BKOPS (1<<10) /* card is doing BKOPS */ |
| 229 | unsigned int quirks; /* card quirks */ | 234 | unsigned int quirks; /* card quirks */ |
| 230 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ | 235 | #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ |
| 231 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ | 236 | #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ |
| @@ -241,11 +246,6 @@ struct mmc_card { | |||
| 241 | #define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ | 246 | #define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ |
| 242 | #define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */ | 247 | #define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */ |
| 243 | /* byte mode */ | 248 | /* byte mode */ |
| 244 | unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */ | ||
| 245 | #define MMC_NO_POWER_NOTIFICATION 0 | ||
| 246 | #define MMC_POWERED_ON 1 | ||
| 247 | #define MMC_POWEROFF_SHORT 2 | ||
| 248 | #define MMC_POWEROFF_LONG 3 | ||
| 249 | 249 | ||
| 250 | unsigned int erase_size; /* erase size in sectors */ | 250 | unsigned int erase_size; /* erase size in sectors */ |
| 251 | unsigned int erase_shift; /* if erase unit is power 2 */ | 251 | unsigned int erase_shift; /* if erase unit is power 2 */ |
| @@ -392,7 +392,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) | |||
| 392 | #define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED) | 392 | #define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED) |
| 393 | #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) | 393 | #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) |
| 394 | #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) | 394 | #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) |
| 395 | #define mmc_card_is_sleep(c) ((c)->state & MMC_STATE_SLEEP) | 395 | #define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS) |
| 396 | 396 | ||
| 397 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) | 397 | #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) |
| 398 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) | 398 | #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) |
| @@ -404,9 +404,9 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) | |||
| 404 | #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED) | 404 | #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED) |
| 405 | #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) | 405 | #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) |
| 406 | #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) | 406 | #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) |
| 407 | #define mmc_card_set_sleep(c) ((c)->state |= MMC_STATE_SLEEP) | 407 | #define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS) |
| 408 | #define mmc_card_clr_doing_bkops(c) ((c)->state &= ~MMC_STATE_DOING_BKOPS) | ||
| 408 | 409 | ||
| 409 | #define mmc_card_clr_sleep(c) ((c)->state &= ~MMC_STATE_SLEEP) | ||
| 410 | /* | 410 | /* |
| 411 | * Quirk add/remove for MMC products. | 411 | * Quirk add/remove for MMC products. |
| 412 | */ | 412 | */ |
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 1b431c728b9a..9b9cdafc7737 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h | |||
| @@ -134,6 +134,8 @@ struct mmc_host; | |||
| 134 | struct mmc_card; | 134 | struct mmc_card; |
| 135 | struct mmc_async_req; | 135 | struct mmc_async_req; |
| 136 | 136 | ||
| 137 | extern int mmc_stop_bkops(struct mmc_card *); | ||
| 138 | extern int mmc_read_bkops_status(struct mmc_card *); | ||
| 137 | extern struct mmc_async_req *mmc_start_req(struct mmc_host *, | 139 | extern struct mmc_async_req *mmc_start_req(struct mmc_host *, |
| 138 | struct mmc_async_req *, int *); | 140 | struct mmc_async_req *, int *); |
| 139 | extern int mmc_interrupt_hpi(struct mmc_card *); | 141 | extern int mmc_interrupt_hpi(struct mmc_card *); |
| @@ -142,6 +144,8 @@ extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int); | |||
| 142 | extern int mmc_app_cmd(struct mmc_host *, struct mmc_card *); | 144 | extern int mmc_app_cmd(struct mmc_host *, struct mmc_card *); |
| 143 | extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, | 145 | extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *, |
| 144 | struct mmc_command *, int); | 146 | struct mmc_command *, int); |
| 147 | extern void mmc_start_bkops(struct mmc_card *card, bool from_exception); | ||
| 148 | extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool); | ||
| 145 | extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); | 149 | extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); |
| 146 | 150 | ||
| 147 | #define MMC_ERASE_ARG 0x00000000 | 151 | #define MMC_ERASE_ARG 0x00000000 |
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 7a7ebd367cfd..7c6a1139d8fa 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h | |||
| @@ -78,6 +78,10 @@ struct mmc_data; | |||
| 78 | * @data_offset: Set the offset of DATA register according to VERID. | 78 | * @data_offset: Set the offset of DATA register according to VERID. |
| 79 | * @dev: Device associated with the MMC controller. | 79 | * @dev: Device associated with the MMC controller. |
| 80 | * @pdata: Platform data associated with the MMC controller. | 80 | * @pdata: Platform data associated with the MMC controller. |
| 81 | * @drv_data: Driver specific data for identified variant of the controller | ||
| 82 | * @priv: Implementation defined private data. | ||
| 83 | * @biu_clk: Pointer to bus interface unit clock instance. | ||
| 84 | * @ciu_clk: Pointer to card interface unit clock instance. | ||
| 81 | * @slot: Slots sharing this MMC controller. | 85 | * @slot: Slots sharing this MMC controller. |
| 82 | * @fifo_depth: depth of FIFO. | 86 | * @fifo_depth: depth of FIFO. |
| 83 | * @data_shift: log2 of FIFO item size. | 87 | * @data_shift: log2 of FIFO item size. |
| @@ -156,8 +160,12 @@ struct dw_mci { | |||
| 156 | u32 fifoth_val; | 160 | u32 fifoth_val; |
| 157 | u16 verid; | 161 | u16 verid; |
| 158 | u16 data_offset; | 162 | u16 data_offset; |
| 159 | struct device dev; | 163 | struct device *dev; |
| 160 | struct dw_mci_board *pdata; | 164 | struct dw_mci_board *pdata; |
| 165 | struct dw_mci_drv_data *drv_data; | ||
| 166 | void *priv; | ||
| 167 | struct clk *biu_clk; | ||
| 168 | struct clk *ciu_clk; | ||
| 161 | struct dw_mci_slot *slot[MAX_MCI_SLOTS]; | 169 | struct dw_mci_slot *slot[MAX_MCI_SLOTS]; |
| 162 | 170 | ||
| 163 | /* FIFO push and pull */ | 171 | /* FIFO push and pull */ |
| @@ -201,7 +209,8 @@ struct dw_mci_dma_ops { | |||
| 201 | #define DW_MCI_QUIRK_HIGHSPEED BIT(2) | 209 | #define DW_MCI_QUIRK_HIGHSPEED BIT(2) |
| 202 | /* Unreliable card detection */ | 210 | /* Unreliable card detection */ |
| 203 | #define DW_MCI_QUIRK_BROKEN_CARD_DETECTION BIT(3) | 211 | #define DW_MCI_QUIRK_BROKEN_CARD_DETECTION BIT(3) |
| 204 | 212 | /* Write Protect detection not available */ | |
| 213 | #define DW_MCI_QUIRK_NO_WRITE_PROTECT BIT(4) | ||
| 205 | 214 | ||
| 206 | struct dma_pdata; | 215 | struct dma_pdata; |
| 207 | 216 | ||
| @@ -218,7 +227,7 @@ struct dw_mci_board { | |||
| 218 | u32 num_slots; | 227 | u32 num_slots; |
| 219 | 228 | ||
| 220 | u32 quirks; /* Workaround / Quirk flags */ | 229 | u32 quirks; /* Workaround / Quirk flags */ |
| 221 | unsigned int bus_hz; /* Bus speed */ | 230 | unsigned int bus_hz; /* Clock speed at the cclk_in pad */ |
| 222 | 231 | ||
| 223 | unsigned int caps; /* Capabilities */ | 232 | unsigned int caps; /* Capabilities */ |
| 224 | unsigned int caps2; /* More capabilities */ | 233 | unsigned int caps2; /* More capabilities */ |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index f578a71d82a6..7abb0e1f7bda 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
| @@ -259,10 +259,6 @@ struct mmc_host { | |||
| 259 | #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ | 259 | #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ |
| 260 | 260 | ||
| 261 | mmc_pm_flag_t pm_caps; /* supported pm features */ | 261 | mmc_pm_flag_t pm_caps; /* supported pm features */ |
| 262 | unsigned int power_notify_type; | ||
| 263 | #define MMC_HOST_PW_NOTIFY_NONE 0 | ||
| 264 | #define MMC_HOST_PW_NOTIFY_SHORT 1 | ||
| 265 | #define MMC_HOST_PW_NOTIFY_LONG 2 | ||
| 266 | 262 | ||
| 267 | #ifdef CONFIG_MMC_CLKGATE | 263 | #ifdef CONFIG_MMC_CLKGATE |
| 268 | int clk_requests; /* internal reference counter */ | 264 | int clk_requests; /* internal reference counter */ |
| @@ -300,6 +296,7 @@ struct mmc_host { | |||
| 300 | #endif | 296 | #endif |
| 301 | 297 | ||
| 302 | int rescan_disable; /* disable card detection */ | 298 | int rescan_disable; /* disable card detection */ |
| 299 | int rescan_entered; /* used with nonremovable devices */ | ||
| 303 | 300 | ||
| 304 | struct mmc_card *card; /* device attached to this host */ | 301 | struct mmc_card *card; /* device attached to this host */ |
| 305 | 302 | ||
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index d425cab144d9..01e4b394029b 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
| @@ -139,6 +139,7 @@ static inline bool mmc_op_multi(u32 opcode) | |||
| 139 | #define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ | 139 | #define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ |
| 140 | #define R1_READY_FOR_DATA (1 << 8) /* sx, a */ | 140 | #define R1_READY_FOR_DATA (1 << 8) /* sx, a */ |
| 141 | #define R1_SWITCH_ERROR (1 << 7) /* sx, c */ | 141 | #define R1_SWITCH_ERROR (1 << 7) /* sx, c */ |
| 142 | #define R1_EXCEPTION_EVENT (1 << 6) /* sx, a */ | ||
| 142 | #define R1_APP_CMD (1 << 5) /* sr, c */ | 143 | #define R1_APP_CMD (1 << 5) /* sr, c */ |
| 143 | 144 | ||
| 144 | #define R1_STATE_IDLE 0 | 145 | #define R1_STATE_IDLE 0 |
| @@ -274,12 +275,15 @@ struct _mmc_csd { | |||
| 274 | #define EXT_CSD_FLUSH_CACHE 32 /* W */ | 275 | #define EXT_CSD_FLUSH_CACHE 32 /* W */ |
| 275 | #define EXT_CSD_CACHE_CTRL 33 /* R/W */ | 276 | #define EXT_CSD_CACHE_CTRL 33 /* R/W */ |
| 276 | #define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */ | 277 | #define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */ |
| 278 | #define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO */ | ||
| 277 | #define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ | 279 | #define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ |
| 278 | #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ | 280 | #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ |
| 279 | #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ | 281 | #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ |
| 280 | #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ | 282 | #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ |
| 281 | #define EXT_CSD_HPI_MGMT 161 /* R/W */ | 283 | #define EXT_CSD_HPI_MGMT 161 /* R/W */ |
| 282 | #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ | 284 | #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ |
| 285 | #define EXT_CSD_BKOPS_EN 163 /* R/W */ | ||
| 286 | #define EXT_CSD_BKOPS_START 164 /* W */ | ||
| 283 | #define EXT_CSD_SANITIZE_START 165 /* W */ | 287 | #define EXT_CSD_SANITIZE_START 165 /* W */ |
| 284 | #define EXT_CSD_WR_REL_PARAM 166 /* RO */ | 288 | #define EXT_CSD_WR_REL_PARAM 166 /* RO */ |
| 285 | #define EXT_CSD_BOOT_WP 173 /* R/W */ | 289 | #define EXT_CSD_BOOT_WP 173 /* R/W */ |
| @@ -313,11 +317,13 @@ struct _mmc_csd { | |||
| 313 | #define EXT_CSD_PWR_CL_200_360 237 /* RO */ | 317 | #define EXT_CSD_PWR_CL_200_360 237 /* RO */ |
| 314 | #define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */ | 318 | #define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */ |
| 315 | #define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */ | 319 | #define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */ |
| 320 | #define EXT_CSD_BKOPS_STATUS 246 /* RO */ | ||
| 316 | #define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */ | 321 | #define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */ |
| 317 | #define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ | 322 | #define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ |
| 318 | #define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ | 323 | #define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ |
| 319 | #define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ | 324 | #define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ |
| 320 | #define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ | 325 | #define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ |
| 326 | #define EXT_CSD_BKOPS_SUPPORT 502 /* RO */ | ||
| 321 | #define EXT_CSD_HPI_FEATURES 503 /* RO */ | 327 | #define EXT_CSD_HPI_FEATURES 503 /* RO */ |
| 322 | 328 | ||
| 323 | /* | 329 | /* |
| @@ -378,6 +384,19 @@ struct _mmc_csd { | |||
| 378 | #define EXT_CSD_PWR_CL_8BIT_SHIFT 4 | 384 | #define EXT_CSD_PWR_CL_8BIT_SHIFT 4 |
| 379 | #define EXT_CSD_PWR_CL_4BIT_SHIFT 0 | 385 | #define EXT_CSD_PWR_CL_4BIT_SHIFT 0 |
| 380 | /* | 386 | /* |
| 387 | * EXCEPTION_EVENT_STATUS field | ||
| 388 | */ | ||
| 389 | #define EXT_CSD_URGENT_BKOPS BIT(0) | ||
| 390 | #define EXT_CSD_DYNCAP_NEEDED BIT(1) | ||
| 391 | #define EXT_CSD_SYSPOOL_EXHAUSTED BIT(2) | ||
| 392 | #define EXT_CSD_PACKED_FAILURE BIT(3) | ||
| 393 | |||
| 394 | /* | ||
| 395 | * BKOPS status level | ||
| 396 | */ | ||
| 397 | #define EXT_CSD_BKOPS_LEVEL_2 0x2 | ||
| 398 | |||
| 399 | /* | ||
| 381 | * MMC_SWITCH access modes | 400 | * MMC_SWITCH access modes |
| 382 | */ | 401 | */ |
| 383 | 402 | ||
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index ac83b105bedd..fa8529a859b8 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h | |||
| @@ -97,7 +97,8 @@ struct sdhci_host { | |||
| 97 | 97 | ||
| 98 | const struct sdhci_ops *ops; /* Low level hw interface */ | 98 | const struct sdhci_ops *ops; /* Low level hw interface */ |
| 99 | 99 | ||
| 100 | struct regulator *vmmc; /* Power regulator */ | 100 | struct regulator *vmmc; /* Power regulator (vmmc) */ |
| 101 | struct regulator *vqmmc; /* Signaling regulator (vccq) */ | ||
| 101 | 102 | ||
| 102 | /* Internal data */ | 103 | /* Internal data */ |
| 103 | struct mmc_host *mmc; /* MMC structure */ | 104 | struct mmc_host *mmc; /* MMC structure */ |
diff --git a/include/linux/platform_data/pxa_sdhci.h b/include/linux/platform_data/pxa_sdhci.h index 51ad0995abac..59acd987ed34 100644 --- a/include/linux/platform_data/pxa_sdhci.h +++ b/include/linux/platform_data/pxa_sdhci.h | |||
| @@ -49,6 +49,7 @@ struct sdhci_pxa_platdata { | |||
| 49 | bool ext_cd_gpio_invert; | 49 | bool ext_cd_gpio_invert; |
| 50 | unsigned int max_speed; | 50 | unsigned int max_speed; |
| 51 | unsigned int host_caps; | 51 | unsigned int host_caps; |
| 52 | unsigned int host_caps2; | ||
| 52 | unsigned int quirks; | 53 | unsigned int quirks; |
| 53 | unsigned int pm_caps; | 54 | unsigned int pm_caps; |
| 54 | }; | 55 | }; |
