diff options
68 files changed, 2152 insertions, 1180 deletions
diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt new file mode 100644 index 000000000000..0cb827bf9435 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | * The simple eMMC hardware reset provider | ||
| 2 | |||
| 3 | The purpose of this driver is to perform standard eMMC hw reset | ||
| 4 | procedure, as descibed by Jedec 4.4 specification. This procedure is | ||
| 5 | performed just after MMC core enabled power to the given mmc host (to | ||
| 6 | fix possible issues if bootloader has left eMMC card in initialized or | ||
| 7 | unknown state), and before performing complete system reboot (also in | ||
| 8 | case of emergency reboot call). The latter is needed on boards, which | ||
| 9 | doesn't have hardware reset logic connected to emmc card and (limited or | ||
| 10 | broken) ROM bootloaders are unable to read second stage from the emmc | ||
| 11 | card if the card is left in unknown or already initialized state. | ||
| 12 | |||
| 13 | Required properties: | ||
| 14 | - compatible : contains "mmc-pwrseq-emmc". | ||
| 15 | - reset-gpios : contains a GPIO specifier. The reset GPIO is asserted | ||
| 16 | and then deasserted to perform eMMC card reset. To perform | ||
| 17 | reset procedure as described in Jedec 4.4 specification, the | ||
| 18 | gpio line should be defined as GPIO_ACTIVE_LOW. | ||
| 19 | |||
| 20 | Example: | ||
| 21 | |||
| 22 | sdhci0_pwrseq { | ||
| 23 | compatible = "mmc-pwrseq-emmc"; | ||
| 24 | reset-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; | ||
| 25 | } | ||
diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt new file mode 100644 index 000000000000..a462c50f19a8 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | * The simple MMC power sequence provider | ||
| 2 | |||
| 3 | The purpose of the simple MMC power sequence provider is to supports a set of | ||
| 4 | common properties between various SOC designs. It thus enables us to use the | ||
| 5 | same provider for several SOC designs. | ||
| 6 | |||
| 7 | Required properties: | ||
| 8 | - compatible : contains "mmc-pwrseq-simple". | ||
| 9 | |||
| 10 | Optional properties: | ||
| 11 | - reset-gpios : contains a list of GPIO specifiers. The reset GPIOs are asserted | ||
| 12 | at initialization and prior we start the power up procedure of the card. | ||
| 13 | They will be de-asserted right after the power has been provided to the | ||
| 14 | card. | ||
| 15 | - clocks : Must contain an entry for the entry in clock-names. | ||
| 16 | See ../clocks/clock-bindings.txt for details. | ||
| 17 | - clock-names : Must include the following entry: | ||
| 18 | "ext_clock" (External clock provided to the card). | ||
| 19 | |||
| 20 | Example: | ||
| 21 | |||
| 22 | sdhci0_pwrseq { | ||
| 23 | compatible = "mmc-pwrseq-simple"; | ||
| 24 | reset-gpios = <&gpio1 12 0>; | ||
| 25 | } | ||
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt index b52628b18a53..438899e8829b 100644 --- a/Documentation/devicetree/bindings/mmc/mmc.txt +++ b/Documentation/devicetree/bindings/mmc/mmc.txt | |||
| @@ -64,7 +64,43 @@ Optional SDIO properties: | |||
| 64 | - keep-power-in-suspend: Preserves card power during a suspend/resume cycle | 64 | - keep-power-in-suspend: Preserves card power during a suspend/resume cycle |
| 65 | - enable-sdio-wakeup: Enables wake up of host system on SDIO IRQ assertion | 65 | - enable-sdio-wakeup: Enables wake up of host system on SDIO IRQ assertion |
| 66 | 66 | ||
| 67 | Example: | 67 | |
| 68 | MMC power sequences: | ||
| 69 | -------------------- | ||
| 70 | |||
| 71 | System on chip designs may specify a specific MMC power sequence. To | ||
| 72 | successfully detect an (e)MMC/SD/SDIO card, that power sequence must be | ||
| 73 | maintained while initializing the card. | ||
| 74 | |||
| 75 | Optional property: | ||
| 76 | - mmc-pwrseq: phandle to the MMC power sequence node. See "mmc-pwrseq-*" | ||
| 77 | for documentation of MMC power sequence bindings. | ||
| 78 | |||
| 79 | |||
| 80 | Use of Function subnodes | ||
| 81 | ------------------------ | ||
| 82 | |||
| 83 | On embedded systems the cards connected to a host may need additional | ||
| 84 | properties. These can be specified in subnodes to the host controller node. | ||
| 85 | The subnodes are identified by the standard 'reg' property. | ||
| 86 | Which information exactly can be specified depends on the bindings for the | ||
| 87 | SDIO function driver for the subnode, as specified by the compatible string. | ||
| 88 | |||
| 89 | Required host node properties when using function subnodes: | ||
| 90 | - #address-cells: should be one. The cell is the slot id. | ||
| 91 | - #size-cells: should be zero. | ||
| 92 | |||
| 93 | Required function subnode properties: | ||
| 94 | - compatible: name of SDIO function following generic names recommended practice | ||
| 95 | - reg: Must contain the SDIO function number of the function this subnode | ||
| 96 | describes. A value of 0 denotes the memory SD function, values from | ||
| 97 | 1 to 7 denote the SDIO functions. | ||
| 98 | |||
| 99 | |||
| 100 | Examples | ||
| 101 | -------- | ||
| 102 | |||
| 103 | Basic example: | ||
| 68 | 104 | ||
| 69 | sdhci@ab000000 { | 105 | sdhci@ab000000 { |
| 70 | compatible = "sdhci"; | 106 | compatible = "sdhci"; |
| @@ -77,4 +113,28 @@ sdhci@ab000000 { | |||
| 77 | max-frequency = <50000000>; | 113 | max-frequency = <50000000>; |
| 78 | keep-power-in-suspend; | 114 | keep-power-in-suspend; |
| 79 | enable-sdio-wakeup; | 115 | enable-sdio-wakeup; |
| 116 | mmc-pwrseq = <&sdhci0_pwrseq> | ||
| 80 | } | 117 | } |
| 118 | |||
| 119 | Example with sdio function subnode: | ||
| 120 | |||
| 121 | mmc3: mmc@01c12000 { | ||
| 122 | #address-cells = <1>; | ||
| 123 | #size-cells = <0>; | ||
| 124 | |||
| 125 | pinctrl-names = "default"; | ||
| 126 | pinctrl-0 = <&mmc3_pins_a>; | ||
| 127 | vmmc-supply = <®_vmmc3>; | ||
| 128 | bus-width = <4>; | ||
| 129 | non-removable; | ||
| 130 | mmc-pwrseq = <&sdhci0_pwrseq> | ||
| 131 | status = "okay"; | ||
| 132 | |||
| 133 | brcmf: bcrmf@1 { | ||
| 134 | reg = <1>; | ||
| 135 | compatible = "brcm,bcm43xx-fmac"; | ||
| 136 | interrupt-parent = <&pio>; | ||
| 137 | interrupts = <10 8>; /* PH10 / EINT10 */ | ||
| 138 | interrupt-names = "host-wake"; | ||
| 139 | }; | ||
| 140 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt b/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt new file mode 100644 index 000000000000..de2c53cff4f1 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | * Fujitsu SDHCI controller | ||
| 2 | |||
| 3 | This file documents differences between the core properties in mmc.txt | ||
| 4 | and the properties used by the sdhci_f_sdh30 driver. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | - compatible: "fujitsu,mb86s70-sdhci-3.0" | ||
| 8 | - clocks: Must contain an entry for each entry in clock-names. It is a | ||
| 9 | list of phandles and clock-specifier pairs. | ||
| 10 | See ../clocks/clock-bindings.txt for details. | ||
| 11 | - clock-names: Should contain the following two entries: | ||
| 12 | "iface" - clock used for sdhci interface | ||
| 13 | "core" - core clock for sdhci controller | ||
| 14 | |||
| 15 | Optional properties: | ||
| 16 | - vqmmc-supply: phandle to the regulator device tree node, mentioned | ||
| 17 | as the VCCQ/VDD_IO supply in the eMMC/SD specs. | ||
| 18 | |||
| 19 | Example: | ||
| 20 | |||
| 21 | sdhci1: mmc@36600000 { | ||
| 22 | compatible = "fujitsu,mb86s70-sdhci-3.0"; | ||
| 23 | reg = <0 0x36600000 0x1000>; | ||
| 24 | interrupts = <0 172 0x4>, | ||
| 25 | <0 173 0x4>; | ||
| 26 | bus-width = <4>; | ||
| 27 | vqmmc-supply = <&vccq_sdhci1>; | ||
| 28 | clocks = <&clock 2 2 0>, <&clock 2 3 0>; | ||
| 29 | clock-names = "iface", "core"; | ||
| 30 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt b/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt index 4dd6deb90719..3d1b449d6097 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt +++ b/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt | |||
| @@ -9,9 +9,13 @@ Required properties: | |||
| 9 | - reg: | 9 | - reg: |
| 10 | * for "mrvl,pxav2-mmc" and "mrvl,pxav3-mmc", one register area for | 10 | * for "mrvl,pxav2-mmc" and "mrvl,pxav3-mmc", one register area for |
| 11 | the SDHCI registers. | 11 | the SDHCI registers. |
| 12 | * for "marvell,armada-380-sdhci", two register areas. The first one | 12 | |
| 13 | for the SDHCI registers themselves, and the second one for the | 13 | * for "marvell,armada-380-sdhci", three register areas. The first |
| 14 | AXI/Mbus bridge registers of the SDHCI unit. | 14 | one for the SDHCI registers themselves, the second one for the |
| 15 | AXI/Mbus bridge registers of the SDHCI unit, the third one for the | ||
| 16 | SDIO3 Configuration register | ||
| 17 | - reg names: should be "sdhci", "mbus", "conf-sdio3". only mandatory | ||
| 18 | for "marvell,armada-380-sdhci" | ||
| 15 | - clocks: Array of clocks required for SDHCI; requires at least one for | 19 | - clocks: Array of clocks required for SDHCI; requires at least one for |
| 16 | I/O clock. | 20 | I/O clock. |
| 17 | - clock-names: Array of names corresponding to clocks property; shall be | 21 | - clock-names: Array of names corresponding to clocks property; shall be |
| @@ -35,7 +39,10 @@ sdhci@d4280800 { | |||
| 35 | 39 | ||
| 36 | sdhci@d8000 { | 40 | sdhci@d8000 { |
| 37 | compatible = "marvell,armada-380-sdhci"; | 41 | compatible = "marvell,armada-380-sdhci"; |
| 38 | reg = <0xd8000 0x1000>, <0xdc000 0x100>; | 42 | reg-names = "sdhci", "mbus", "conf-sdio3"; |
| 43 | reg = <0xd8000 0x1000>, | ||
| 44 | <0xdc000 0x100>; | ||
| 45 | <0x18454 0x4>; | ||
| 39 | interrupts = <0 25 0x4>; | 46 | interrupts = <0 25 0x4>; |
| 40 | clocks = <&gateclk 17>; | 47 | clocks = <&gateclk 17>; |
| 41 | clock-names = "io"; | 48 | clock-names = "io"; |
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 7f1708738c30..969e1003dd92 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c | |||
| @@ -254,12 +254,14 @@ static void pandora_wl1251_init_card(struct mmc_card *card) | |||
| 254 | * We have TI wl1251 attached to MMC3. Pass this information to | 254 | * We have TI wl1251 attached to MMC3. Pass this information to |
| 255 | * SDIO core because it can't be probed by normal methods. | 255 | * SDIO core because it can't be probed by normal methods. |
| 256 | */ | 256 | */ |
| 257 | card->quirks |= MMC_QUIRK_NONSTD_SDIO; | 257 | if (card->type == MMC_TYPE_SDIO || card->type == MMC_TYPE_SD_COMBO) { |
| 258 | card->cccr.wide_bus = 1; | 258 | card->quirks |= MMC_QUIRK_NONSTD_SDIO; |
| 259 | card->cis.vendor = 0x104c; | 259 | card->cccr.wide_bus = 1; |
| 260 | card->cis.device = 0x9066; | 260 | card->cis.vendor = 0x104c; |
| 261 | card->cis.blksize = 512; | 261 | card->cis.device = 0x9066; |
| 262 | card->cis.max_dtr = 20000000; | 262 | card->cis.blksize = 512; |
| 263 | card->cis.max_dtr = 20000000; | ||
| 264 | } | ||
| 263 | } | 265 | } |
| 264 | 266 | ||
| 265 | static struct omap2_hsmmc_info omap3pandora_mmc[] = { | 267 | static struct omap2_hsmmc_info omap3pandora_mmc[] = { |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 4409d79ed650..c69afb5e264e 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
| @@ -2147,7 +2147,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, | |||
| 2147 | */ | 2147 | */ |
| 2148 | 2148 | ||
| 2149 | snprintf(md->disk->disk_name, sizeof(md->disk->disk_name), | 2149 | snprintf(md->disk->disk_name, sizeof(md->disk->disk_name), |
| 2150 | "mmcblk%d%s", md->name_idx, subname ? subname : ""); | 2150 | "mmcblk%u%s", md->name_idx, subname ? subname : ""); |
| 2151 | 2151 | ||
| 2152 | if (mmc_card_mmc(card)) | 2152 | if (mmc_card_mmc(card)) |
| 2153 | blk_queue_logical_block_size(md->queue.queue, | 2153 | blk_queue_logical_block_size(md->queue.queue, |
| @@ -2193,7 +2193,6 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, | |||
| 2193 | static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | 2193 | static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) |
| 2194 | { | 2194 | { |
| 2195 | sector_t size; | 2195 | sector_t size; |
| 2196 | struct mmc_blk_data *md; | ||
| 2197 | 2196 | ||
| 2198 | if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { | 2197 | if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { |
| 2199 | /* | 2198 | /* |
| @@ -2209,9 +2208,8 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
| 2209 | size = card->csd.capacity << (card->csd.read_blkbits - 9); | 2208 | size = card->csd.capacity << (card->csd.read_blkbits - 9); |
| 2210 | } | 2209 | } |
| 2211 | 2210 | ||
| 2212 | md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL, | 2211 | return mmc_blk_alloc_req(card, &card->dev, size, false, NULL, |
| 2213 | MMC_BLK_DATA_AREA_MAIN); | 2212 | MMC_BLK_DATA_AREA_MAIN); |
| 2214 | return md; | ||
| 2215 | } | 2213 | } |
| 2216 | 2214 | ||
| 2217 | static int mmc_blk_alloc_part(struct mmc_card *card, | 2215 | static int mmc_blk_alloc_part(struct mmc_card *card, |
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 0a7430f94d29..7dac4695163b 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c | |||
| @@ -2342,20 +2342,16 @@ static int mmc_test_hw_reset(struct mmc_test_card *test) | |||
| 2342 | struct mmc_host *host = card->host; | 2342 | struct mmc_host *host = card->host; |
| 2343 | int err; | 2343 | int err; |
| 2344 | 2344 | ||
| 2345 | err = mmc_hw_reset_check(host); | 2345 | if (!mmc_card_mmc(card) || !mmc_can_reset(card)) |
| 2346 | return RESULT_UNSUP_CARD; | ||
| 2347 | |||
| 2348 | err = mmc_hw_reset(host); | ||
| 2346 | if (!err) | 2349 | if (!err) |
| 2347 | return RESULT_OK; | 2350 | return RESULT_OK; |
| 2351 | else if (err == -EOPNOTSUPP) | ||
| 2352 | return RESULT_UNSUP_HOST; | ||
| 2348 | 2353 | ||
| 2349 | if (err == -ENOSYS) | 2354 | return RESULT_FAIL; |
| 2350 | return RESULT_FAIL; | ||
| 2351 | |||
| 2352 | if (err != -EOPNOTSUPP) | ||
| 2353 | return err; | ||
| 2354 | |||
| 2355 | if (!mmc_can_reset(card)) | ||
| 2356 | return RESULT_UNSUP_CARD; | ||
| 2357 | |||
| 2358 | return RESULT_UNSUP_HOST; | ||
| 2359 | } | 2355 | } |
| 2360 | 2356 | ||
| 2361 | static const struct mmc_test_case mmc_test_cases[] = { | 2357 | static const struct mmc_test_case mmc_test_cases[] = { |
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 38ed210ce2f3..2c25138f28b7 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile | |||
| @@ -8,5 +8,5 @@ mmc_core-y := core.o bus.o host.o \ | |||
| 8 | sdio.o sdio_ops.o sdio_bus.o \ | 8 | sdio.o sdio_ops.o sdio_bus.o \ |
| 9 | sdio_cis.o sdio_io.o sdio_irq.o \ | 9 | sdio_cis.o sdio_io.o sdio_irq.o \ |
| 10 | quirks.o slot-gpio.o | 10 | quirks.o slot-gpio.o |
| 11 | 11 | mmc_core-$(CONFIG_OF) += pwrseq.o pwrseq_simple.o pwrseq_emmc.o | |
| 12 | mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o | 12 | mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o |
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 86d271148528..c5ef10065a4a 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/stat.h> | 18 | #include <linux/stat.h> |
| 19 | #include <linux/of.h> | ||
| 19 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
| 20 | 21 | ||
| 21 | #include <linux/mmc/card.h> | 22 | #include <linux/mmc/card.h> |
| @@ -321,6 +322,8 @@ int mmc_add_card(struct mmc_card *card) | |||
| 321 | #endif | 322 | #endif |
| 322 | mmc_init_context_info(card->host); | 323 | mmc_init_context_info(card->host); |
| 323 | 324 | ||
| 325 | card->dev.of_node = mmc_of_find_child_device(card->host, 0); | ||
| 326 | |||
| 324 | ret = device_add(&card->dev); | 327 | ret = device_add(&card->dev); |
| 325 | if (ret) | 328 | if (ret) |
| 326 | return ret; | 329 | return ret; |
| @@ -349,6 +352,7 @@ void mmc_remove_card(struct mmc_card *card) | |||
| 349 | mmc_hostname(card->host), card->rca); | 352 | mmc_hostname(card->host), card->rca); |
| 350 | } | 353 | } |
| 351 | device_del(&card->dev); | 354 | device_del(&card->dev); |
| 355 | of_node_put(card->dev.of_node); | ||
| 352 | } | 356 | } |
| 353 | 357 | ||
| 354 | put_device(&card->dev); | 358 | put_device(&card->dev); |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 9584bffa8b22..23f10f72e5f3 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include "bus.h" | 40 | #include "bus.h" |
| 41 | #include "host.h" | 41 | #include "host.h" |
| 42 | #include "sdio_bus.h" | 42 | #include "sdio_bus.h" |
| 43 | #include "pwrseq.h" | ||
| 43 | 44 | ||
| 44 | #include "mmc_ops.h" | 45 | #include "mmc_ops.h" |
| 45 | #include "sd_ops.h" | 46 | #include "sd_ops.h" |
| @@ -185,13 +186,14 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) | |||
| 185 | 186 | ||
| 186 | EXPORT_SYMBOL(mmc_request_done); | 187 | EXPORT_SYMBOL(mmc_request_done); |
| 187 | 188 | ||
| 188 | static void | 189 | static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) |
| 189 | mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) | ||
| 190 | { | 190 | { |
| 191 | #ifdef CONFIG_MMC_DEBUG | 191 | #ifdef CONFIG_MMC_DEBUG |
| 192 | unsigned int i, sz; | 192 | unsigned int i, sz; |
| 193 | struct scatterlist *sg; | 193 | struct scatterlist *sg; |
| 194 | #endif | 194 | #endif |
| 195 | if (mmc_card_removed(host->card)) | ||
| 196 | return -ENOMEDIUM; | ||
| 195 | 197 | ||
| 196 | if (mrq->sbc) { | 198 | if (mrq->sbc) { |
| 197 | pr_debug("<%s: starting CMD%u arg %08x flags %08x>\n", | 199 | pr_debug("<%s: starting CMD%u arg %08x flags %08x>\n", |
| @@ -251,6 +253,8 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) | |||
| 251 | mmc_host_clk_hold(host); | 253 | mmc_host_clk_hold(host); |
| 252 | led_trigger_event(host->led, LED_FULL); | 254 | led_trigger_event(host->led, LED_FULL); |
| 253 | host->ops->request(host, mrq); | 255 | host->ops->request(host, mrq); |
| 256 | |||
| 257 | return 0; | ||
| 254 | } | 258 | } |
| 255 | 259 | ||
| 256 | /** | 260 | /** |
| @@ -271,7 +275,7 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception) | |||
| 271 | 275 | ||
| 272 | BUG_ON(!card); | 276 | BUG_ON(!card); |
| 273 | 277 | ||
| 274 | if (!card->ext_csd.bkops_en || mmc_card_doing_bkops(card)) | 278 | if (!card->ext_csd.man_bkops_en || mmc_card_doing_bkops(card)) |
| 275 | return; | 279 | return; |
| 276 | 280 | ||
| 277 | err = mmc_read_bkops_status(card); | 281 | err = mmc_read_bkops_status(card); |
| @@ -345,29 +349,34 @@ static void mmc_wait_done(struct mmc_request *mrq) | |||
| 345 | */ | 349 | */ |
| 346 | static int __mmc_start_data_req(struct mmc_host *host, struct mmc_request *mrq) | 350 | static int __mmc_start_data_req(struct mmc_host *host, struct mmc_request *mrq) |
| 347 | { | 351 | { |
| 352 | int err; | ||
| 353 | |||
| 348 | mrq->done = mmc_wait_data_done; | 354 | mrq->done = mmc_wait_data_done; |
| 349 | mrq->host = host; | 355 | mrq->host = host; |
| 350 | if (mmc_card_removed(host->card)) { | 356 | |
| 351 | mrq->cmd->error = -ENOMEDIUM; | 357 | err = mmc_start_request(host, mrq); |
| 358 | if (err) { | ||
| 359 | mrq->cmd->error = err; | ||
| 352 | mmc_wait_data_done(mrq); | 360 | mmc_wait_data_done(mrq); |
| 353 | return -ENOMEDIUM; | ||
| 354 | } | 361 | } |
| 355 | mmc_start_request(host, mrq); | ||
| 356 | 362 | ||
| 357 | return 0; | 363 | return err; |
| 358 | } | 364 | } |
| 359 | 365 | ||
| 360 | static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) | 366 | static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) |
| 361 | { | 367 | { |
| 368 | int err; | ||
| 369 | |||
| 362 | init_completion(&mrq->completion); | 370 | init_completion(&mrq->completion); |
| 363 | mrq->done = mmc_wait_done; | 371 | mrq->done = mmc_wait_done; |
| 364 | if (mmc_card_removed(host->card)) { | 372 | |
| 365 | mrq->cmd->error = -ENOMEDIUM; | 373 | err = mmc_start_request(host, mrq); |
| 374 | if (err) { | ||
| 375 | mrq->cmd->error = err; | ||
| 366 | complete(&mrq->completion); | 376 | complete(&mrq->completion); |
| 367 | return -ENOMEDIUM; | ||
| 368 | } | 377 | } |
| 369 | mmc_start_request(host, mrq); | 378 | |
| 370 | return 0; | 379 | return err; |
| 371 | } | 380 | } |
| 372 | 381 | ||
| 373 | /* | 382 | /* |
| @@ -1077,6 +1086,30 @@ void mmc_set_ungated(struct mmc_host *host) | |||
| 1077 | } | 1086 | } |
| 1078 | #endif | 1087 | #endif |
| 1079 | 1088 | ||
| 1089 | int mmc_execute_tuning(struct mmc_card *card) | ||
| 1090 | { | ||
| 1091 | struct mmc_host *host = card->host; | ||
| 1092 | u32 opcode; | ||
| 1093 | int err; | ||
| 1094 | |||
| 1095 | if (!host->ops->execute_tuning) | ||
| 1096 | return 0; | ||
| 1097 | |||
| 1098 | if (mmc_card_mmc(card)) | ||
| 1099 | opcode = MMC_SEND_TUNING_BLOCK_HS200; | ||
| 1100 | else | ||
| 1101 | opcode = MMC_SEND_TUNING_BLOCK; | ||
| 1102 | |||
| 1103 | mmc_host_clk_hold(host); | ||
| 1104 | err = host->ops->execute_tuning(host, opcode); | ||
| 1105 | mmc_host_clk_release(host); | ||
| 1106 | |||
| 1107 | if (err) | ||
| 1108 | pr_err("%s: tuning execution failed\n", mmc_hostname(host)); | ||
| 1109 | |||
| 1110 | return err; | ||
| 1111 | } | ||
| 1112 | |||
| 1080 | /* | 1113 | /* |
| 1081 | * Change the bus mode (open drain/push-pull) of a host. | 1114 | * Change the bus mode (open drain/push-pull) of a host. |
| 1082 | */ | 1115 | */ |
| @@ -1232,6 +1265,34 @@ EXPORT_SYMBOL(mmc_of_parse_voltage); | |||
| 1232 | 1265 | ||
| 1233 | #endif /* CONFIG_OF */ | 1266 | #endif /* CONFIG_OF */ |
| 1234 | 1267 | ||
| 1268 | static int mmc_of_get_func_num(struct device_node *node) | ||
| 1269 | { | ||
| 1270 | u32 reg; | ||
| 1271 | int ret; | ||
| 1272 | |||
| 1273 | ret = of_property_read_u32(node, "reg", ®); | ||
| 1274 | if (ret < 0) | ||
| 1275 | return ret; | ||
| 1276 | |||
| 1277 | return reg; | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | struct device_node *mmc_of_find_child_device(struct mmc_host *host, | ||
| 1281 | unsigned func_num) | ||
| 1282 | { | ||
| 1283 | struct device_node *node; | ||
| 1284 | |||
| 1285 | if (!host->parent || !host->parent->of_node) | ||
| 1286 | return NULL; | ||
| 1287 | |||
| 1288 | for_each_child_of_node(host->parent->of_node, node) { | ||
| 1289 | if (mmc_of_get_func_num(node) == func_num) | ||
| 1290 | return node; | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | return NULL; | ||
| 1294 | } | ||
| 1295 | |||
| 1235 | #ifdef CONFIG_REGULATOR | 1296 | #ifdef CONFIG_REGULATOR |
| 1236 | 1297 | ||
| 1237 | /** | 1298 | /** |
| @@ -1555,6 +1616,8 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) | |||
| 1555 | 1616 | ||
| 1556 | mmc_host_clk_hold(host); | 1617 | mmc_host_clk_hold(host); |
| 1557 | 1618 | ||
| 1619 | mmc_pwrseq_pre_power_on(host); | ||
| 1620 | |||
| 1558 | host->ios.vdd = fls(ocr) - 1; | 1621 | host->ios.vdd = fls(ocr) - 1; |
| 1559 | host->ios.power_mode = MMC_POWER_UP; | 1622 | host->ios.power_mode = MMC_POWER_UP; |
| 1560 | /* Set initial state and call mmc_set_ios */ | 1623 | /* Set initial state and call mmc_set_ios */ |
| @@ -1574,6 +1637,8 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) | |||
| 1574 | */ | 1637 | */ |
| 1575 | mmc_delay(10); | 1638 | mmc_delay(10); |
| 1576 | 1639 | ||
| 1640 | mmc_pwrseq_post_power_on(host); | ||
| 1641 | |||
| 1577 | host->ios.clock = host->f_init; | 1642 | host->ios.clock = host->f_init; |
| 1578 | 1643 | ||
| 1579 | host->ios.power_mode = MMC_POWER_ON; | 1644 | host->ios.power_mode = MMC_POWER_ON; |
| @@ -1595,6 +1660,8 @@ void mmc_power_off(struct mmc_host *host) | |||
| 1595 | 1660 | ||
| 1596 | mmc_host_clk_hold(host); | 1661 | mmc_host_clk_hold(host); |
| 1597 | 1662 | ||
| 1663 | mmc_pwrseq_power_off(host); | ||
| 1664 | |||
| 1598 | host->ios.clock = 0; | 1665 | host->ios.clock = 0; |
| 1599 | host->ios.vdd = 0; | 1666 | host->ios.vdd = 0; |
| 1600 | 1667 | ||
| @@ -2245,67 +2312,28 @@ static void mmc_hw_reset_for_init(struct mmc_host *host) | |||
| 2245 | mmc_host_clk_release(host); | 2312 | mmc_host_clk_release(host); |
| 2246 | } | 2313 | } |
| 2247 | 2314 | ||
| 2248 | int mmc_can_reset(struct mmc_card *card) | 2315 | int mmc_hw_reset(struct mmc_host *host) |
| 2249 | { | ||
| 2250 | u8 rst_n_function; | ||
| 2251 | |||
| 2252 | if (!mmc_card_mmc(card)) | ||
| 2253 | return 0; | ||
| 2254 | rst_n_function = card->ext_csd.rst_n_function; | ||
| 2255 | if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) != EXT_CSD_RST_N_ENABLED) | ||
| 2256 | return 0; | ||
| 2257 | return 1; | ||
| 2258 | } | ||
| 2259 | EXPORT_SYMBOL(mmc_can_reset); | ||
| 2260 | |||
| 2261 | static int mmc_do_hw_reset(struct mmc_host *host, int check) | ||
| 2262 | { | 2316 | { |
| 2263 | struct mmc_card *card = host->card; | 2317 | int ret; |
| 2264 | |||
| 2265 | if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) | ||
| 2266 | return -EOPNOTSUPP; | ||
| 2267 | 2318 | ||
| 2268 | if (!card) | 2319 | if (!host->card) |
| 2269 | return -EINVAL; | 2320 | return -EINVAL; |
| 2270 | 2321 | ||
| 2271 | if (!mmc_can_reset(card)) | 2322 | mmc_bus_get(host); |
| 2323 | if (!host->bus_ops || host->bus_dead || !host->bus_ops->reset) { | ||
| 2324 | mmc_bus_put(host); | ||
| 2272 | return -EOPNOTSUPP; | 2325 | return -EOPNOTSUPP; |
| 2273 | |||
| 2274 | mmc_host_clk_hold(host); | ||
| 2275 | mmc_set_clock(host, host->f_init); | ||
| 2276 | |||
| 2277 | host->ops->hw_reset(host); | ||
| 2278 | |||
| 2279 | /* If the reset has happened, then a status command will fail */ | ||
| 2280 | if (check) { | ||
| 2281 | u32 status; | ||
| 2282 | |||
| 2283 | if (!mmc_send_status(card, &status)) { | ||
| 2284 | mmc_host_clk_release(host); | ||
| 2285 | return -ENOSYS; | ||
| 2286 | } | ||
| 2287 | } | 2326 | } |
| 2288 | 2327 | ||
| 2289 | /* Set initial state and call mmc_set_ios */ | 2328 | ret = host->bus_ops->reset(host); |
| 2290 | mmc_set_initial_state(host); | 2329 | mmc_bus_put(host); |
| 2291 | 2330 | ||
| 2292 | mmc_host_clk_release(host); | 2331 | pr_warn("%s: tried to reset card\n", mmc_hostname(host)); |
| 2293 | 2332 | ||
| 2294 | return host->bus_ops->power_restore(host); | 2333 | return ret; |
| 2295 | } | ||
| 2296 | |||
| 2297 | int mmc_hw_reset(struct mmc_host *host) | ||
| 2298 | { | ||
| 2299 | return mmc_do_hw_reset(host, 0); | ||
| 2300 | } | 2334 | } |
| 2301 | EXPORT_SYMBOL(mmc_hw_reset); | 2335 | EXPORT_SYMBOL(mmc_hw_reset); |
| 2302 | 2336 | ||
| 2303 | int mmc_hw_reset_check(struct mmc_host *host) | ||
| 2304 | { | ||
| 2305 | return mmc_do_hw_reset(host, 1); | ||
| 2306 | } | ||
| 2307 | EXPORT_SYMBOL(mmc_hw_reset_check); | ||
| 2308 | |||
| 2309 | static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) | 2337 | static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) |
| 2310 | { | 2338 | { |
| 2311 | host->f_init = freq; | 2339 | host->f_init = freq; |
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index d76597c65e3a..cfba3c05aab1 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
| @@ -27,11 +27,15 @@ struct mmc_bus_ops { | |||
| 27 | int (*power_restore)(struct mmc_host *); | 27 | int (*power_restore)(struct mmc_host *); |
| 28 | int (*alive)(struct mmc_host *); | 28 | int (*alive)(struct mmc_host *); |
| 29 | int (*shutdown)(struct mmc_host *); | 29 | int (*shutdown)(struct mmc_host *); |
| 30 | int (*reset)(struct mmc_host *); | ||
| 30 | }; | 31 | }; |
| 31 | 32 | ||
| 32 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); | 33 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); |
| 33 | void mmc_detach_bus(struct mmc_host *host); | 34 | void mmc_detach_bus(struct mmc_host *host); |
| 34 | 35 | ||
| 36 | struct device_node *mmc_of_find_child_device(struct mmc_host *host, | ||
| 37 | unsigned func_num); | ||
| 38 | |||
| 35 | void mmc_init_erase(struct mmc_card *card); | 39 | void mmc_init_erase(struct mmc_card *card); |
| 36 | 40 | ||
| 37 | void mmc_set_chip_select(struct mmc_host *host, int mode); | 41 | void mmc_set_chip_select(struct mmc_host *host, int mode); |
| @@ -82,5 +86,8 @@ void mmc_add_card_debugfs(struct mmc_card *card); | |||
| 82 | void mmc_remove_card_debugfs(struct mmc_card *card); | 86 | void mmc_remove_card_debugfs(struct mmc_card *card); |
| 83 | 87 | ||
| 84 | void mmc_init_context_info(struct mmc_host *host); | 88 | void mmc_init_context_info(struct mmc_host *host); |
| 89 | |||
| 90 | int mmc_execute_tuning(struct mmc_card *card); | ||
| 91 | |||
| 85 | #endif | 92 | #endif |
| 86 | 93 | ||
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 270d58a4c43d..8be0df758e68 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
| @@ -29,13 +29,20 @@ | |||
| 29 | 29 | ||
| 30 | #include "core.h" | 30 | #include "core.h" |
| 31 | #include "host.h" | 31 | #include "host.h" |
| 32 | #include "slot-gpio.h" | ||
| 33 | #include "pwrseq.h" | ||
| 32 | 34 | ||
| 33 | #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) | 35 | #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) |
| 34 | 36 | ||
| 37 | static DEFINE_IDR(mmc_host_idr); | ||
| 38 | static DEFINE_SPINLOCK(mmc_host_lock); | ||
| 39 | |||
| 35 | static void mmc_host_classdev_release(struct device *dev) | 40 | static void mmc_host_classdev_release(struct device *dev) |
| 36 | { | 41 | { |
| 37 | struct mmc_host *host = cls_dev_to_mmc_host(dev); | 42 | struct mmc_host *host = cls_dev_to_mmc_host(dev); |
| 38 | mutex_destroy(&host->slot.lock); | 43 | spin_lock(&mmc_host_lock); |
| 44 | idr_remove(&mmc_host_idr, host->index); | ||
| 45 | spin_unlock(&mmc_host_lock); | ||
| 39 | kfree(host); | 46 | kfree(host); |
| 40 | } | 47 | } |
| 41 | 48 | ||
| @@ -54,9 +61,6 @@ void mmc_unregister_host_class(void) | |||
| 54 | class_unregister(&mmc_host_class); | 61 | class_unregister(&mmc_host_class); |
| 55 | } | 62 | } |
| 56 | 63 | ||
| 57 | static DEFINE_IDR(mmc_host_idr); | ||
| 58 | static DEFINE_SPINLOCK(mmc_host_lock); | ||
| 59 | |||
| 60 | #ifdef CONFIG_MMC_CLKGATE | 64 | #ifdef CONFIG_MMC_CLKGATE |
| 61 | static ssize_t clkgate_delay_show(struct device *dev, | 65 | static ssize_t clkgate_delay_show(struct device *dev, |
| 62 | struct device_attribute *attr, char *buf) | 66 | struct device_attribute *attr, char *buf) |
| @@ -367,16 +371,10 @@ int mmc_of_parse(struct mmc_host *host) | |||
| 367 | 371 | ||
| 368 | ret = mmc_gpiod_request_cd(host, "cd", 0, true, | 372 | ret = mmc_gpiod_request_cd(host, "cd", 0, true, |
| 369 | 0, &cd_gpio_invert); | 373 | 0, &cd_gpio_invert); |
| 370 | if (ret) { | 374 | if (!ret) |
| 371 | if (ret == -EPROBE_DEFER) | ||
| 372 | return ret; | ||
| 373 | if (ret != -ENOENT) { | ||
| 374 | dev_err(host->parent, | ||
| 375 | "Failed to request CD GPIO: %d\n", | ||
| 376 | ret); | ||
| 377 | } | ||
| 378 | } else | ||
| 379 | dev_info(host->parent, "Got CD GPIO\n"); | 375 | dev_info(host->parent, "Got CD GPIO\n"); |
| 376 | else if (ret != -ENOENT) | ||
| 377 | return ret; | ||
| 380 | 378 | ||
| 381 | /* | 379 | /* |
| 382 | * There are two ways to flag that the CD line is inverted: | 380 | * There are two ways to flag that the CD line is inverted: |
| @@ -397,16 +395,10 @@ int mmc_of_parse(struct mmc_host *host) | |||
| 397 | ro_cap_invert = of_property_read_bool(np, "wp-inverted"); | 395 | ro_cap_invert = of_property_read_bool(np, "wp-inverted"); |
| 398 | 396 | ||
| 399 | ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert); | 397 | ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert); |
| 400 | if (ret) { | 398 | if (!ret) |
| 401 | if (ret == -EPROBE_DEFER) | ||
| 402 | goto out; | ||
| 403 | if (ret != -ENOENT) { | ||
| 404 | dev_err(host->parent, | ||
| 405 | "Failed to request WP GPIO: %d\n", | ||
| 406 | ret); | ||
| 407 | } | ||
| 408 | } else | ||
| 409 | dev_info(host->parent, "Got WP GPIO\n"); | 399 | dev_info(host->parent, "Got WP GPIO\n"); |
| 400 | else if (ret != -ENOENT) | ||
| 401 | return ret; | ||
| 410 | 402 | ||
| 411 | /* See the comment on CD inversion above */ | 403 | /* See the comment on CD inversion above */ |
| 412 | if (ro_cap_invert ^ ro_gpio_invert) | 404 | if (ro_cap_invert ^ ro_gpio_invert) |
| @@ -457,11 +449,7 @@ int mmc_of_parse(struct mmc_host *host) | |||
| 457 | host->dsr_req = 0; | 449 | host->dsr_req = 0; |
| 458 | } | 450 | } |
| 459 | 451 | ||
| 460 | return 0; | 452 | return mmc_pwrseq_alloc(host); |
| 461 | |||
| 462 | out: | ||
| 463 | mmc_gpio_free_cd(host); | ||
| 464 | return ret; | ||
| 465 | } | 453 | } |
| 466 | 454 | ||
| 467 | EXPORT_SYMBOL(mmc_of_parse); | 455 | EXPORT_SYMBOL(mmc_of_parse); |
| @@ -491,8 +479,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | |||
| 491 | host->index = err; | 479 | host->index = err; |
| 492 | spin_unlock(&mmc_host_lock); | 480 | spin_unlock(&mmc_host_lock); |
| 493 | idr_preload_end(); | 481 | idr_preload_end(); |
| 494 | if (err < 0) | 482 | if (err < 0) { |
| 495 | goto free; | 483 | kfree(host); |
| 484 | return NULL; | ||
| 485 | } | ||
| 496 | 486 | ||
| 497 | dev_set_name(&host->class_dev, "mmc%d", host->index); | 487 | dev_set_name(&host->class_dev, "mmc%d", host->index); |
| 498 | 488 | ||
| @@ -501,10 +491,12 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | |||
| 501 | host->class_dev.class = &mmc_host_class; | 491 | host->class_dev.class = &mmc_host_class; |
| 502 | device_initialize(&host->class_dev); | 492 | device_initialize(&host->class_dev); |
| 503 | 493 | ||
| 504 | mmc_host_clk_init(host); | 494 | if (mmc_gpio_alloc(host)) { |
| 495 | put_device(&host->class_dev); | ||
| 496 | return NULL; | ||
| 497 | } | ||
| 505 | 498 | ||
| 506 | mutex_init(&host->slot.lock); | 499 | mmc_host_clk_init(host); |
| 507 | host->slot.cd_irq = -EINVAL; | ||
| 508 | 500 | ||
| 509 | spin_lock_init(&host->lock); | 501 | spin_lock_init(&host->lock); |
| 510 | init_waitqueue_head(&host->wq); | 502 | init_waitqueue_head(&host->wq); |
| @@ -525,10 +517,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | |||
| 525 | host->max_blk_count = PAGE_CACHE_SIZE / 512; | 517 | host->max_blk_count = PAGE_CACHE_SIZE / 512; |
| 526 | 518 | ||
| 527 | return host; | 519 | return host; |
| 528 | |||
| 529 | free: | ||
| 530 | kfree(host); | ||
| 531 | return NULL; | ||
| 532 | } | 520 | } |
| 533 | 521 | ||
| 534 | EXPORT_SYMBOL(mmc_alloc_host); | 522 | EXPORT_SYMBOL(mmc_alloc_host); |
| @@ -601,10 +589,7 @@ EXPORT_SYMBOL(mmc_remove_host); | |||
| 601 | */ | 589 | */ |
| 602 | void mmc_free_host(struct mmc_host *host) | 590 | void mmc_free_host(struct mmc_host *host) |
| 603 | { | 591 | { |
| 604 | spin_lock(&mmc_host_lock); | 592 | mmc_pwrseq_free(host); |
| 605 | idr_remove(&mmc_host_idr, host->index); | ||
| 606 | spin_unlock(&mmc_host_lock); | ||
| 607 | |||
| 608 | put_device(&host->class_dev); | 593 | put_device(&host->class_dev); |
| 609 | } | 594 | } |
| 610 | 595 | ||
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 7466ce098e60..1d41e8541f38 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
| @@ -483,11 +483,13 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
| 483 | /* check whether the eMMC card supports BKOPS */ | 483 | /* check whether the eMMC card supports BKOPS */ |
| 484 | if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { | 484 | if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { |
| 485 | card->ext_csd.bkops = 1; | 485 | card->ext_csd.bkops = 1; |
| 486 | card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN]; | 486 | card->ext_csd.man_bkops_en = |
| 487 | (ext_csd[EXT_CSD_BKOPS_EN] & | ||
| 488 | EXT_CSD_MANUAL_BKOPS_MASK); | ||
| 487 | card->ext_csd.raw_bkops_status = | 489 | card->ext_csd.raw_bkops_status = |
| 488 | ext_csd[EXT_CSD_BKOPS_STATUS]; | 490 | ext_csd[EXT_CSD_BKOPS_STATUS]; |
| 489 | if (!card->ext_csd.bkops_en) | 491 | if (!card->ext_csd.man_bkops_en) |
| 490 | pr_info("%s: BKOPS_EN bit is not set\n", | 492 | pr_info("%s: MAN_BKOPS_EN bit is not set\n", |
| 491 | mmc_hostname(card->host)); | 493 | mmc_hostname(card->host)); |
| 492 | } | 494 | } |
| 493 | 495 | ||
| @@ -1155,38 +1157,6 @@ bus_speed: | |||
| 1155 | return err; | 1157 | return err; |
| 1156 | } | 1158 | } |
| 1157 | 1159 | ||
| 1158 | const u8 tuning_blk_pattern_4bit[MMC_TUNING_BLK_PATTERN_4BIT_SIZE] = { | ||
| 1159 | 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, | ||
| 1160 | 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, | ||
| 1161 | 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, | ||
| 1162 | 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, | ||
| 1163 | 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, | ||
| 1164 | 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, | ||
| 1165 | 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, | ||
| 1166 | 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, | ||
| 1167 | }; | ||
| 1168 | EXPORT_SYMBOL(tuning_blk_pattern_4bit); | ||
| 1169 | |||
| 1170 | const u8 tuning_blk_pattern_8bit[MMC_TUNING_BLK_PATTERN_8BIT_SIZE] = { | ||
| 1171 | 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, | ||
| 1172 | 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, | ||
| 1173 | 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, | ||
| 1174 | 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, | ||
| 1175 | 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, | ||
| 1176 | 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, | ||
| 1177 | 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, | ||
| 1178 | 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, | ||
| 1179 | 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, | ||
| 1180 | 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, | ||
| 1181 | 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, | ||
| 1182 | 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, | ||
| 1183 | 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, | ||
| 1184 | 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, | ||
| 1185 | 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, | ||
| 1186 | 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, | ||
| 1187 | }; | ||
| 1188 | EXPORT_SYMBOL(tuning_blk_pattern_8bit); | ||
| 1189 | |||
| 1190 | /* | 1160 | /* |
| 1191 | * Execute tuning sequence to seek the proper bus operating | 1161 | * Execute tuning sequence to seek the proper bus operating |
| 1192 | * conditions for HS200 and HS400, which sends CMD21 to the device. | 1162 | * conditions for HS200 and HS400, which sends CMD21 to the device. |
| @@ -1194,7 +1164,6 @@ EXPORT_SYMBOL(tuning_blk_pattern_8bit); | |||
| 1194 | static int mmc_hs200_tuning(struct mmc_card *card) | 1164 | static int mmc_hs200_tuning(struct mmc_card *card) |
| 1195 | { | 1165 | { |
| 1196 | struct mmc_host *host = card->host; | 1166 | struct mmc_host *host = card->host; |
| 1197 | int err = 0; | ||
| 1198 | 1167 | ||
| 1199 | /* | 1168 | /* |
| 1200 | * Timing should be adjusted to the HS400 target | 1169 | * Timing should be adjusted to the HS400 target |
| @@ -1205,18 +1174,7 @@ static int mmc_hs200_tuning(struct mmc_card *card) | |||
| 1205 | if (host->ops->prepare_hs400_tuning) | 1174 | if (host->ops->prepare_hs400_tuning) |
| 1206 | host->ops->prepare_hs400_tuning(host, &host->ios); | 1175 | host->ops->prepare_hs400_tuning(host, &host->ios); |
| 1207 | 1176 | ||
| 1208 | if (host->ops->execute_tuning) { | 1177 | return mmc_execute_tuning(card); |
| 1209 | mmc_host_clk_hold(host); | ||
| 1210 | err = host->ops->execute_tuning(host, | ||
| 1211 | MMC_SEND_TUNING_BLOCK_HS200); | ||
| 1212 | mmc_host_clk_release(host); | ||
| 1213 | |||
| 1214 | if (err) | ||
| 1215 | pr_err("%s: tuning execution failed\n", | ||
| 1216 | mmc_hostname(host)); | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | return err; | ||
| 1220 | } | 1178 | } |
| 1221 | 1179 | ||
| 1222 | /* | 1180 | /* |
| @@ -1297,6 +1255,12 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 1297 | } | 1255 | } |
| 1298 | 1256 | ||
| 1299 | /* | 1257 | /* |
| 1258 | * Call the optional HC's init_card function to handle quirks. | ||
| 1259 | */ | ||
| 1260 | if (host->ops->init_card) | ||
| 1261 | host->ops->init_card(host, card); | ||
| 1262 | |||
| 1263 | /* | ||
| 1300 | * For native busses: set card RCA and quit open drain mode. | 1264 | * For native busses: set card RCA and quit open drain mode. |
| 1301 | */ | 1265 | */ |
| 1302 | if (!mmc_host_is_spi(host)) { | 1266 | if (!mmc_host_is_spi(host)) { |
| @@ -1821,6 +1785,46 @@ static int mmc_power_restore(struct mmc_host *host) | |||
| 1821 | return ret; | 1785 | return ret; |
| 1822 | } | 1786 | } |
| 1823 | 1787 | ||
| 1788 | int mmc_can_reset(struct mmc_card *card) | ||
| 1789 | { | ||
| 1790 | u8 rst_n_function; | ||
| 1791 | |||
| 1792 | rst_n_function = card->ext_csd.rst_n_function; | ||
| 1793 | if ((rst_n_function & EXT_CSD_RST_N_EN_MASK) != EXT_CSD_RST_N_ENABLED) | ||
| 1794 | return 0; | ||
| 1795 | return 1; | ||
| 1796 | } | ||
| 1797 | EXPORT_SYMBOL(mmc_can_reset); | ||
| 1798 | |||
| 1799 | static int mmc_reset(struct mmc_host *host) | ||
| 1800 | { | ||
| 1801 | struct mmc_card *card = host->card; | ||
| 1802 | u32 status; | ||
| 1803 | |||
| 1804 | if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) | ||
| 1805 | return -EOPNOTSUPP; | ||
| 1806 | |||
| 1807 | if (!mmc_can_reset(card)) | ||
| 1808 | return -EOPNOTSUPP; | ||
| 1809 | |||
| 1810 | mmc_host_clk_hold(host); | ||
| 1811 | mmc_set_clock(host, host->f_init); | ||
| 1812 | |||
| 1813 | host->ops->hw_reset(host); | ||
| 1814 | |||
| 1815 | /* If the reset has happened, then a status command will fail */ | ||
| 1816 | if (!mmc_send_status(card, &status)) { | ||
| 1817 | mmc_host_clk_release(host); | ||
| 1818 | return -ENOSYS; | ||
| 1819 | } | ||
| 1820 | |||
| 1821 | /* Set initial state and call mmc_set_ios */ | ||
| 1822 | mmc_set_initial_state(host); | ||
| 1823 | mmc_host_clk_release(host); | ||
| 1824 | |||
| 1825 | return mmc_power_restore(host); | ||
| 1826 | } | ||
| 1827 | |||
| 1824 | static const struct mmc_bus_ops mmc_ops = { | 1828 | static const struct mmc_bus_ops mmc_ops = { |
| 1825 | .remove = mmc_remove, | 1829 | .remove = mmc_remove, |
| 1826 | .detect = mmc_detect, | 1830 | .detect = mmc_detect, |
| @@ -1831,6 +1835,7 @@ static const struct mmc_bus_ops mmc_ops = { | |||
| 1831 | .power_restore = mmc_power_restore, | 1835 | .power_restore = mmc_power_restore, |
| 1832 | .alive = mmc_alive, | 1836 | .alive = mmc_alive, |
| 1833 | .shutdown = mmc_shutdown, | 1837 | .shutdown = mmc_shutdown, |
| 1838 | .reset = mmc_reset, | ||
| 1834 | }; | 1839 | }; |
| 1835 | 1840 | ||
| 1836 | /* | 1841 | /* |
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 3b044c5b029c..0ea042dc7443 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c | |||
| @@ -23,6 +23,36 @@ | |||
| 23 | 23 | ||
| 24 | #define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ | 24 | #define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ |
| 25 | 25 | ||
| 26 | static const u8 tuning_blk_pattern_4bit[] = { | ||
| 27 | 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, | ||
| 28 | 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, | ||
| 29 | 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, | ||
| 30 | 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, | ||
| 31 | 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, | ||
| 32 | 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, | ||
| 33 | 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, | ||
| 34 | 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, | ||
| 35 | }; | ||
| 36 | |||
| 37 | static const u8 tuning_blk_pattern_8bit[] = { | ||
| 38 | 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, | ||
| 39 | 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, | ||
| 40 | 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, | ||
| 41 | 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, | ||
| 42 | 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, | ||
| 43 | 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, | ||
| 44 | 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, | ||
| 45 | 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, | ||
| 46 | 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, | ||
| 47 | 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, | ||
| 48 | 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, | ||
| 49 | 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, | ||
| 50 | 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, | ||
| 51 | 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, | ||
| 52 | 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, | ||
| 53 | 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, | ||
| 54 | }; | ||
| 55 | |||
| 26 | static inline int __mmc_send_status(struct mmc_card *card, u32 *status, | 56 | static inline int __mmc_send_status(struct mmc_card *card, u32 *status, |
| 27 | bool ignore_crc) | 57 | bool ignore_crc) |
| 28 | { | 58 | { |
diff --git a/drivers/mmc/core/pwrseq.c b/drivers/mmc/core/pwrseq.c new file mode 100644 index 000000000000..862356123d78 --- /dev/null +++ b/drivers/mmc/core/pwrseq.c | |||
| @@ -0,0 +1,112 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 Linaro Ltd | ||
| 3 | * | ||
| 4 | * Author: Ulf Hansson <ulf.hansson@linaro.org> | ||
| 5 | * | ||
| 6 | * License terms: GNU General Public License (GPL) version 2 | ||
| 7 | * | ||
| 8 | * MMC power sequence management | ||
| 9 | */ | ||
| 10 | #include <linux/kernel.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | #include <linux/err.h> | ||
| 13 | #include <linux/of.h> | ||
| 14 | #include <linux/of_platform.h> | ||
| 15 | |||
| 16 | #include <linux/mmc/host.h> | ||
| 17 | |||
| 18 | #include "pwrseq.h" | ||
| 19 | |||
| 20 | struct mmc_pwrseq_match { | ||
| 21 | const char *compatible; | ||
| 22 | int (*alloc)(struct mmc_host *host, struct device *dev); | ||
| 23 | }; | ||
| 24 | |||
| 25 | static struct mmc_pwrseq_match pwrseq_match[] = { | ||
| 26 | { | ||
| 27 | .compatible = "mmc-pwrseq-simple", | ||
| 28 | .alloc = mmc_pwrseq_simple_alloc, | ||
| 29 | }, { | ||
| 30 | .compatible = "mmc-pwrseq-emmc", | ||
| 31 | .alloc = mmc_pwrseq_emmc_alloc, | ||
| 32 | }, | ||
| 33 | }; | ||
| 34 | |||
| 35 | static struct mmc_pwrseq_match *mmc_pwrseq_find(struct device_node *np) | ||
| 36 | { | ||
| 37 | struct mmc_pwrseq_match *match = ERR_PTR(-ENODEV); | ||
| 38 | int i; | ||
| 39 | |||
| 40 | for (i = 0; i < ARRAY_SIZE(pwrseq_match); i++) { | ||
| 41 | if (of_device_is_compatible(np, pwrseq_match[i].compatible)) { | ||
| 42 | match = &pwrseq_match[i]; | ||
| 43 | break; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | return match; | ||
| 48 | } | ||
| 49 | |||
| 50 | int mmc_pwrseq_alloc(struct mmc_host *host) | ||
| 51 | { | ||
| 52 | struct platform_device *pdev; | ||
| 53 | struct device_node *np; | ||
| 54 | struct mmc_pwrseq_match *match; | ||
| 55 | int ret = 0; | ||
| 56 | |||
| 57 | np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0); | ||
| 58 | if (!np) | ||
| 59 | return 0; | ||
| 60 | |||
| 61 | pdev = of_find_device_by_node(np); | ||
| 62 | if (!pdev) { | ||
| 63 | ret = -ENODEV; | ||
| 64 | goto err; | ||
| 65 | } | ||
| 66 | |||
| 67 | match = mmc_pwrseq_find(np); | ||
| 68 | if (IS_ERR(match)) { | ||
| 69 | ret = PTR_ERR(match); | ||
| 70 | goto err; | ||
| 71 | } | ||
| 72 | |||
| 73 | ret = match->alloc(host, &pdev->dev); | ||
| 74 | if (!ret) | ||
| 75 | dev_info(host->parent, "allocated mmc-pwrseq\n"); | ||
| 76 | |||
| 77 | err: | ||
| 78 | of_node_put(np); | ||
| 79 | return ret; | ||
| 80 | } | ||
| 81 | |||
| 82 | void mmc_pwrseq_pre_power_on(struct mmc_host *host) | ||
| 83 | { | ||
| 84 | struct mmc_pwrseq *pwrseq = host->pwrseq; | ||
| 85 | |||
| 86 | if (pwrseq && pwrseq->ops && pwrseq->ops->pre_power_on) | ||
| 87 | pwrseq->ops->pre_power_on(host); | ||
| 88 | } | ||
| 89 | |||
| 90 | void mmc_pwrseq_post_power_on(struct mmc_host *host) | ||
| 91 | { | ||
| 92 | struct mmc_pwrseq *pwrseq = host->pwrseq; | ||
| 93 | |||
| 94 | if (pwrseq && pwrseq->ops && pwrseq->ops->post_power_on) | ||
| 95 | pwrseq->ops->post_power_on(host); | ||
| 96 | } | ||
| 97 | |||
| 98 | void mmc_pwrseq_power_off(struct mmc_host *host) | ||
| 99 | { | ||
| 100 | struct mmc_pwrseq *pwrseq = host->pwrseq; | ||
| 101 | |||
| 102 | if (pwrseq && pwrseq->ops && pwrseq->ops->power_off) | ||
| 103 | pwrseq->ops->power_off(host); | ||
| 104 | } | ||
| 105 | |||
| 106 | void mmc_pwrseq_free(struct mmc_host *host) | ||
| 107 | { | ||
| 108 | struct mmc_pwrseq *pwrseq = host->pwrseq; | ||
| 109 | |||
| 110 | if (pwrseq && pwrseq->ops && pwrseq->ops->free) | ||
| 111 | pwrseq->ops->free(host); | ||
| 112 | } | ||
diff --git a/drivers/mmc/core/pwrseq.h b/drivers/mmc/core/pwrseq.h new file mode 100644 index 000000000000..aba3409e8d6e --- /dev/null +++ b/drivers/mmc/core/pwrseq.h | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 Linaro Ltd | ||
| 3 | * | ||
| 4 | * Author: Ulf Hansson <ulf.hansson@linaro.org> | ||
| 5 | * | ||
| 6 | * License terms: GNU General Public License (GPL) version 2 | ||
| 7 | */ | ||
| 8 | #ifndef _MMC_CORE_PWRSEQ_H | ||
| 9 | #define _MMC_CORE_PWRSEQ_H | ||
| 10 | |||
| 11 | struct mmc_pwrseq_ops { | ||
| 12 | void (*pre_power_on)(struct mmc_host *host); | ||
| 13 | void (*post_power_on)(struct mmc_host *host); | ||
| 14 | void (*power_off)(struct mmc_host *host); | ||
| 15 | void (*free)(struct mmc_host *host); | ||
| 16 | }; | ||
| 17 | |||
| 18 | struct mmc_pwrseq { | ||
| 19 | struct mmc_pwrseq_ops *ops; | ||
| 20 | }; | ||
| 21 | |||
| 22 | #ifdef CONFIG_OF | ||
| 23 | |||
| 24 | int mmc_pwrseq_alloc(struct mmc_host *host); | ||
| 25 | void mmc_pwrseq_pre_power_on(struct mmc_host *host); | ||
| 26 | void mmc_pwrseq_post_power_on(struct mmc_host *host); | ||
| 27 | void mmc_pwrseq_power_off(struct mmc_host *host); | ||
| 28 | void mmc_pwrseq_free(struct mmc_host *host); | ||
| 29 | |||
| 30 | int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev); | ||
| 31 | int mmc_pwrseq_emmc_alloc(struct mmc_host *host, struct device *dev); | ||
| 32 | |||
| 33 | #else | ||
| 34 | |||
| 35 | static inline int mmc_pwrseq_alloc(struct mmc_host *host) { return 0; } | ||
| 36 | static inline void mmc_pwrseq_pre_power_on(struct mmc_host *host) {} | ||
| 37 | static inline void mmc_pwrseq_post_power_on(struct mmc_host *host) {} | ||
| 38 | static inline void mmc_pwrseq_power_off(struct mmc_host *host) {} | ||
| 39 | static inline void mmc_pwrseq_free(struct mmc_host *host) {} | ||
| 40 | |||
| 41 | #endif | ||
| 42 | |||
| 43 | #endif | ||
diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c new file mode 100644 index 000000000000..a2d545904fbf --- /dev/null +++ b/drivers/mmc/core/pwrseq_emmc.c | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2015, Samsung Electronics Co., Ltd. | ||
| 3 | * | ||
| 4 | * Author: Marek Szyprowski <m.szyprowski@samsung.com> | ||
| 5 | * | ||
| 6 | * License terms: GNU General Public License (GPL) version 2 | ||
| 7 | * | ||
| 8 | * Simple eMMC hardware reset provider | ||
| 9 | */ | ||
| 10 | #include <linux/delay.h> | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/slab.h> | ||
| 13 | #include <linux/device.h> | ||
| 14 | #include <linux/err.h> | ||
| 15 | #include <linux/gpio/consumer.h> | ||
| 16 | #include <linux/reboot.h> | ||
| 17 | |||
| 18 | #include <linux/mmc/host.h> | ||
| 19 | |||
| 20 | #include "pwrseq.h" | ||
| 21 | |||
| 22 | struct mmc_pwrseq_emmc { | ||
| 23 | struct mmc_pwrseq pwrseq; | ||
| 24 | struct notifier_block reset_nb; | ||
| 25 | struct gpio_desc *reset_gpio; | ||
| 26 | }; | ||
| 27 | |||
| 28 | static void __mmc_pwrseq_emmc_reset(struct mmc_pwrseq_emmc *pwrseq) | ||
| 29 | { | ||
| 30 | gpiod_set_value(pwrseq->reset_gpio, 1); | ||
| 31 | udelay(1); | ||
| 32 | gpiod_set_value(pwrseq->reset_gpio, 0); | ||
| 33 | udelay(200); | ||
| 34 | } | ||
| 35 | |||
| 36 | static void mmc_pwrseq_emmc_reset(struct mmc_host *host) | ||
| 37 | { | ||
| 38 | struct mmc_pwrseq_emmc *pwrseq = container_of(host->pwrseq, | ||
| 39 | struct mmc_pwrseq_emmc, pwrseq); | ||
| 40 | |||
| 41 | __mmc_pwrseq_emmc_reset(pwrseq); | ||
| 42 | } | ||
| 43 | |||
| 44 | static void mmc_pwrseq_emmc_free(struct mmc_host *host) | ||
| 45 | { | ||
| 46 | struct mmc_pwrseq_emmc *pwrseq = container_of(host->pwrseq, | ||
| 47 | struct mmc_pwrseq_emmc, pwrseq); | ||
| 48 | |||
| 49 | unregister_restart_handler(&pwrseq->reset_nb); | ||
| 50 | gpiod_put(pwrseq->reset_gpio); | ||
| 51 | kfree(pwrseq); | ||
| 52 | host->pwrseq = NULL; | ||
| 53 | } | ||
| 54 | |||
| 55 | static struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { | ||
| 56 | .post_power_on = mmc_pwrseq_emmc_reset, | ||
| 57 | .free = mmc_pwrseq_emmc_free, | ||
| 58 | }; | ||
| 59 | |||
| 60 | static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, | ||
| 61 | unsigned long mode, void *cmd) | ||
| 62 | { | ||
| 63 | struct mmc_pwrseq_emmc *pwrseq = container_of(this, | ||
| 64 | struct mmc_pwrseq_emmc, reset_nb); | ||
| 65 | |||
| 66 | __mmc_pwrseq_emmc_reset(pwrseq); | ||
| 67 | return NOTIFY_DONE; | ||
| 68 | } | ||
| 69 | |||
| 70 | int mmc_pwrseq_emmc_alloc(struct mmc_host *host, struct device *dev) | ||
| 71 | { | ||
| 72 | struct mmc_pwrseq_emmc *pwrseq; | ||
| 73 | int ret = 0; | ||
| 74 | |||
| 75 | pwrseq = kzalloc(sizeof(struct mmc_pwrseq_emmc), GFP_KERNEL); | ||
| 76 | if (!pwrseq) | ||
| 77 | return -ENOMEM; | ||
| 78 | |||
| 79 | pwrseq->reset_gpio = gpiod_get_index(dev, "reset", 0, GPIOD_OUT_LOW); | ||
| 80 | if (IS_ERR(pwrseq->reset_gpio)) { | ||
| 81 | ret = PTR_ERR(pwrseq->reset_gpio); | ||
| 82 | goto free; | ||
| 83 | } | ||
| 84 | |||
| 85 | /* | ||
| 86 | * register reset handler to ensure emmc reset also from | ||
| 87 | * emergency_reboot(), priority 129 schedules it just before | ||
| 88 | * system reboot | ||
| 89 | */ | ||
| 90 | pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb; | ||
| 91 | pwrseq->reset_nb.priority = 129; | ||
| 92 | register_restart_handler(&pwrseq->reset_nb); | ||
| 93 | |||
| 94 | pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; | ||
| 95 | host->pwrseq = &pwrseq->pwrseq; | ||
| 96 | |||
| 97 | return 0; | ||
| 98 | free: | ||
| 99 | kfree(pwrseq); | ||
| 100 | return ret; | ||
| 101 | } | ||
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c new file mode 100644 index 000000000000..e9f1d8d84613 --- /dev/null +++ b/drivers/mmc/core/pwrseq_simple.c | |||
| @@ -0,0 +1,145 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 Linaro Ltd | ||
| 3 | * | ||
| 4 | * Author: Ulf Hansson <ulf.hansson@linaro.org> | ||
| 5 | * | ||
| 6 | * License terms: GNU General Public License (GPL) version 2 | ||
| 7 | * | ||
| 8 | * Simple MMC power sequence management | ||
| 9 | */ | ||
| 10 | #include <linux/clk.h> | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/slab.h> | ||
| 13 | #include <linux/device.h> | ||
| 14 | #include <linux/err.h> | ||
| 15 | #include <linux/of_gpio.h> | ||
| 16 | #include <linux/gpio/consumer.h> | ||
| 17 | |||
| 18 | #include <linux/mmc/host.h> | ||
| 19 | |||
| 20 | #include "pwrseq.h" | ||
| 21 | |||
| 22 | struct mmc_pwrseq_simple { | ||
| 23 | struct mmc_pwrseq pwrseq; | ||
| 24 | bool clk_enabled; | ||
| 25 | struct clk *ext_clk; | ||
| 26 | int nr_gpios; | ||
| 27 | struct gpio_desc *reset_gpios[0]; | ||
| 28 | }; | ||
| 29 | |||
| 30 | static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq, | ||
| 31 | int value) | ||
| 32 | { | ||
| 33 | int i; | ||
| 34 | |||
| 35 | for (i = 0; i < pwrseq->nr_gpios; i++) | ||
| 36 | if (!IS_ERR(pwrseq->reset_gpios[i])) | ||
| 37 | gpiod_set_value_cansleep(pwrseq->reset_gpios[i], value); | ||
| 38 | } | ||
| 39 | |||
| 40 | static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) | ||
| 41 | { | ||
| 42 | struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, | ||
| 43 | struct mmc_pwrseq_simple, pwrseq); | ||
| 44 | |||
| 45 | if (!IS_ERR(pwrseq->ext_clk) && !pwrseq->clk_enabled) { | ||
| 46 | clk_prepare_enable(pwrseq->ext_clk); | ||
| 47 | pwrseq->clk_enabled = true; | ||
| 48 | } | ||
| 49 | |||
| 50 | mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); | ||
| 51 | } | ||
| 52 | |||
| 53 | static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host) | ||
| 54 | { | ||
| 55 | struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, | ||
| 56 | struct mmc_pwrseq_simple, pwrseq); | ||
| 57 | |||
| 58 | mmc_pwrseq_simple_set_gpios_value(pwrseq, 0); | ||
| 59 | } | ||
| 60 | |||
| 61 | static void mmc_pwrseq_simple_power_off(struct mmc_host *host) | ||
| 62 | { | ||
| 63 | struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, | ||
| 64 | struct mmc_pwrseq_simple, pwrseq); | ||
| 65 | |||
| 66 | mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); | ||
| 67 | |||
| 68 | if (!IS_ERR(pwrseq->ext_clk) && pwrseq->clk_enabled) { | ||
| 69 | clk_disable_unprepare(pwrseq->ext_clk); | ||
| 70 | pwrseq->clk_enabled = false; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | static void mmc_pwrseq_simple_free(struct mmc_host *host) | ||
| 75 | { | ||
| 76 | struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, | ||
| 77 | struct mmc_pwrseq_simple, pwrseq); | ||
| 78 | int i; | ||
| 79 | |||
| 80 | for (i = 0; i < pwrseq->nr_gpios; i++) | ||
| 81 | if (!IS_ERR(pwrseq->reset_gpios[i])) | ||
| 82 | gpiod_put(pwrseq->reset_gpios[i]); | ||
| 83 | |||
| 84 | if (!IS_ERR(pwrseq->ext_clk)) | ||
| 85 | clk_put(pwrseq->ext_clk); | ||
| 86 | |||
| 87 | kfree(pwrseq); | ||
| 88 | host->pwrseq = NULL; | ||
| 89 | } | ||
| 90 | |||
| 91 | static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { | ||
| 92 | .pre_power_on = mmc_pwrseq_simple_pre_power_on, | ||
| 93 | .post_power_on = mmc_pwrseq_simple_post_power_on, | ||
| 94 | .power_off = mmc_pwrseq_simple_power_off, | ||
| 95 | .free = mmc_pwrseq_simple_free, | ||
| 96 | }; | ||
| 97 | |||
| 98 | int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev) | ||
| 99 | { | ||
| 100 | struct mmc_pwrseq_simple *pwrseq; | ||
| 101 | int i, nr_gpios, ret = 0; | ||
| 102 | |||
| 103 | nr_gpios = of_gpio_named_count(dev->of_node, "reset-gpios"); | ||
| 104 | if (nr_gpios < 0) | ||
| 105 | nr_gpios = 0; | ||
| 106 | |||
| 107 | pwrseq = kzalloc(sizeof(struct mmc_pwrseq_simple) + nr_gpios * | ||
| 108 | sizeof(struct gpio_desc *), GFP_KERNEL); | ||
| 109 | if (!pwrseq) | ||
| 110 | return -ENOMEM; | ||
| 111 | |||
| 112 | pwrseq->ext_clk = clk_get(dev, "ext_clock"); | ||
| 113 | if (IS_ERR(pwrseq->ext_clk) && | ||
| 114 | PTR_ERR(pwrseq->ext_clk) != -ENOENT) { | ||
| 115 | ret = PTR_ERR(pwrseq->ext_clk); | ||
| 116 | goto free; | ||
| 117 | } | ||
| 118 | |||
| 119 | for (i = 0; i < nr_gpios; i++) { | ||
| 120 | pwrseq->reset_gpios[i] = gpiod_get_index(dev, "reset", i, | ||
| 121 | GPIOD_OUT_HIGH); | ||
| 122 | if (IS_ERR(pwrseq->reset_gpios[i]) && | ||
| 123 | PTR_ERR(pwrseq->reset_gpios[i]) != -ENOENT && | ||
| 124 | PTR_ERR(pwrseq->reset_gpios[i]) != -ENOSYS) { | ||
| 125 | ret = PTR_ERR(pwrseq->reset_gpios[i]); | ||
| 126 | |||
| 127 | while (--i) | ||
| 128 | gpiod_put(pwrseq->reset_gpios[i]); | ||
| 129 | |||
| 130 | goto clk_put; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | pwrseq->nr_gpios = nr_gpios; | ||
| 135 | pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; | ||
| 136 | host->pwrseq = &pwrseq->pwrseq; | ||
| 137 | |||
| 138 | return 0; | ||
| 139 | clk_put: | ||
| 140 | if (!IS_ERR(pwrseq->ext_clk)) | ||
| 141 | clk_put(pwrseq->ext_clk); | ||
| 142 | free: | ||
| 143 | kfree(pwrseq); | ||
| 144 | return ret; | ||
| 145 | } | ||
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index d90a6de7901d..ad4d43eae99d 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
| @@ -660,15 +660,10 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) | |||
| 660 | * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and | 660 | * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and |
| 661 | * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. | 661 | * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. |
| 662 | */ | 662 | */ |
| 663 | if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning && | 663 | if (!mmc_host_is_spi(card->host) && |
| 664 | (card->sd_bus_speed == UHS_SDR50_BUS_SPEED || | 664 | (card->sd_bus_speed == UHS_SDR50_BUS_SPEED || |
| 665 | card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) { | 665 | card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) |
| 666 | mmc_host_clk_hold(card->host); | 666 | err = mmc_execute_tuning(card); |
| 667 | err = card->host->ops->execute_tuning(card->host, | ||
| 668 | MMC_SEND_TUNING_BLOCK); | ||
| 669 | mmc_host_clk_release(card->host); | ||
| 670 | } | ||
| 671 | |||
| 672 | out: | 667 | out: |
| 673 | kfree(status); | 668 | kfree(status); |
| 674 | 669 | ||
| @@ -933,6 +928,12 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | |||
| 933 | } | 928 | } |
| 934 | 929 | ||
| 935 | /* | 930 | /* |
| 931 | * Call the optional HC's init_card function to handle quirks. | ||
| 932 | */ | ||
| 933 | if (host->ops->init_card) | ||
| 934 | host->ops->init_card(host, card); | ||
| 935 | |||
| 936 | /* | ||
| 936 | * For native busses: get card RCA and quit open drain mode. | 937 | * For native busses: get card RCA and quit open drain mode. |
| 937 | */ | 938 | */ |
| 938 | if (!mmc_host_is_spi(host)) { | 939 | if (!mmc_host_is_spi(host)) { |
| @@ -1191,6 +1192,12 @@ static int mmc_sd_power_restore(struct mmc_host *host) | |||
| 1191 | return ret; | 1192 | return ret; |
| 1192 | } | 1193 | } |
| 1193 | 1194 | ||
| 1195 | static int mmc_sd_reset(struct mmc_host *host) | ||
| 1196 | { | ||
| 1197 | mmc_power_cycle(host, host->card->ocr); | ||
| 1198 | return mmc_sd_power_restore(host); | ||
| 1199 | } | ||
| 1200 | |||
| 1194 | static const struct mmc_bus_ops mmc_sd_ops = { | 1201 | static const struct mmc_bus_ops mmc_sd_ops = { |
| 1195 | .remove = mmc_sd_remove, | 1202 | .remove = mmc_sd_remove, |
| 1196 | .detect = mmc_sd_detect, | 1203 | .detect = mmc_sd_detect, |
| @@ -1201,6 +1208,7 @@ static const struct mmc_bus_ops mmc_sd_ops = { | |||
| 1201 | .power_restore = mmc_sd_power_restore, | 1208 | .power_restore = mmc_sd_power_restore, |
| 1202 | .alive = mmc_sd_alive, | 1209 | .alive = mmc_sd_alive, |
| 1203 | .shutdown = mmc_sd_suspend, | 1210 | .shutdown = mmc_sd_suspend, |
| 1211 | .reset = mmc_sd_reset, | ||
| 1204 | }; | 1212 | }; |
| 1205 | 1213 | ||
| 1206 | /* | 1214 | /* |
| @@ -1271,4 +1279,3 @@ err: | |||
| 1271 | 1279 | ||
| 1272 | return err; | 1280 | return err; |
| 1273 | } | 1281 | } |
| 1274 | |||
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index fd0750b5a634..ce6cc47206b0 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
| @@ -567,17 +567,11 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card) | |||
| 567 | * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and | 567 | * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and |
| 568 | * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. | 568 | * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. |
| 569 | */ | 569 | */ |
| 570 | if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning && | 570 | if (!mmc_host_is_spi(card->host) && |
| 571 | ((card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50) || | 571 | ((card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50) || |
| 572 | (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104))) { | 572 | (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104))) |
| 573 | mmc_host_clk_hold(card->host); | 573 | err = mmc_execute_tuning(card); |
| 574 | err = card->host->ops->execute_tuning(card->host, | ||
| 575 | MMC_SEND_TUNING_BLOCK); | ||
| 576 | mmc_host_clk_release(card->host); | ||
| 577 | } | ||
| 578 | |||
| 579 | out: | 574 | out: |
| 580 | |||
| 581 | return err; | 575 | return err; |
| 582 | } | 576 | } |
| 583 | 577 | ||
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 60885316afba..bee02e644d62 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c | |||
| @@ -22,7 +22,9 @@ | |||
| 22 | #include <linux/mmc/card.h> | 22 | #include <linux/mmc/card.h> |
| 23 | #include <linux/mmc/host.h> | 23 | #include <linux/mmc/host.h> |
| 24 | #include <linux/mmc/sdio_func.h> | 24 | #include <linux/mmc/sdio_func.h> |
| 25 | #include <linux/of.h> | ||
| 25 | 26 | ||
| 27 | #include "core.h" | ||
| 26 | #include "sdio_cis.h" | 28 | #include "sdio_cis.h" |
| 27 | #include "sdio_bus.h" | 29 | #include "sdio_bus.h" |
| 28 | 30 | ||
| @@ -295,6 +297,13 @@ static void sdio_acpi_set_handle(struct sdio_func *func) | |||
| 295 | static inline void sdio_acpi_set_handle(struct sdio_func *func) {} | 297 | static inline void sdio_acpi_set_handle(struct sdio_func *func) {} |
| 296 | #endif | 298 | #endif |
| 297 | 299 | ||
| 300 | static void sdio_set_of_node(struct sdio_func *func) | ||
| 301 | { | ||
| 302 | struct mmc_host *host = func->card->host; | ||
| 303 | |||
| 304 | func->dev.of_node = mmc_of_find_child_device(host, func->num); | ||
| 305 | } | ||
| 306 | |||
| 298 | /* | 307 | /* |
| 299 | * Register a new SDIO function with the driver model. | 308 | * Register a new SDIO function with the driver model. |
| 300 | */ | 309 | */ |
| @@ -304,6 +313,7 @@ int sdio_add_func(struct sdio_func *func) | |||
| 304 | 313 | ||
| 305 | dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num); | 314 | dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num); |
| 306 | 315 | ||
| 316 | sdio_set_of_node(func); | ||
| 307 | sdio_acpi_set_handle(func); | 317 | sdio_acpi_set_handle(func); |
| 308 | ret = device_add(&func->dev); | 318 | ret = device_add(&func->dev); |
| 309 | if (ret == 0) { | 319 | if (ret == 0) { |
| @@ -327,6 +337,7 @@ void sdio_remove_func(struct sdio_func *func) | |||
| 327 | 337 | ||
| 328 | dev_pm_domain_detach(&func->dev, false); | 338 | dev_pm_domain_detach(&func->dev, false); |
| 329 | device_del(&func->dev); | 339 | device_del(&func->dev); |
| 340 | of_node_put(func->dev.of_node); | ||
| 330 | put_device(&func->dev); | 341 | put_device(&func->dev); |
| 331 | } | 342 | } |
| 332 | 343 | ||
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 69bbf2adb329..27117ba47073 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c | |||
| @@ -18,11 +18,14 @@ | |||
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | 20 | ||
| 21 | #include "slot-gpio.h" | ||
| 22 | |||
| 21 | struct mmc_gpio { | 23 | struct mmc_gpio { |
| 22 | struct gpio_desc *ro_gpio; | 24 | struct gpio_desc *ro_gpio; |
| 23 | struct gpio_desc *cd_gpio; | 25 | struct gpio_desc *cd_gpio; |
| 24 | bool override_ro_active_level; | 26 | bool override_ro_active_level; |
| 25 | bool override_cd_active_level; | 27 | bool override_cd_active_level; |
| 28 | irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id); | ||
| 26 | char *ro_label; | 29 | char *ro_label; |
| 27 | char cd_label[0]; | 30 | char cd_label[0]; |
| 28 | }; | 31 | }; |
| @@ -38,32 +41,20 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) | |||
| 38 | return IRQ_HANDLED; | 41 | return IRQ_HANDLED; |
| 39 | } | 42 | } |
| 40 | 43 | ||
| 41 | static int mmc_gpio_alloc(struct mmc_host *host) | 44 | int mmc_gpio_alloc(struct mmc_host *host) |
| 42 | { | 45 | { |
| 43 | size_t len = strlen(dev_name(host->parent)) + 4; | 46 | size_t len = strlen(dev_name(host->parent)) + 4; |
| 44 | struct mmc_gpio *ctx; | 47 | struct mmc_gpio *ctx = devm_kzalloc(host->parent, |
| 45 | 48 | sizeof(*ctx) + 2 * len, GFP_KERNEL); | |
| 46 | mutex_lock(&host->slot.lock); | 49 | |
| 47 | 50 | if (ctx) { | |
| 48 | ctx = host->slot.handler_priv; | 51 | ctx->ro_label = ctx->cd_label + len; |
| 49 | if (!ctx) { | 52 | snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); |
| 50 | /* | 53 | snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent)); |
| 51 | * devm_kzalloc() can be called after device_initialize(), even | 54 | host->slot.handler_priv = ctx; |
| 52 | * before device_add(), i.e., between mmc_alloc_host() and | 55 | host->slot.cd_irq = -EINVAL; |
| 53 | * mmc_add_host() | ||
| 54 | */ | ||
| 55 | ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len, | ||
| 56 | GFP_KERNEL); | ||
| 57 | if (ctx) { | ||
| 58 | ctx->ro_label = ctx->cd_label + len; | ||
| 59 | snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); | ||
| 60 | snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent)); | ||
| 61 | host->slot.handler_priv = ctx; | ||
| 62 | } | ||
| 63 | } | 56 | } |
| 64 | 57 | ||
| 65 | mutex_unlock(&host->slot.lock); | ||
| 66 | |||
| 67 | return ctx ? 0 : -ENOMEM; | 58 | return ctx ? 0 : -ENOMEM; |
| 68 | } | 59 | } |
| 69 | 60 | ||
| @@ -103,29 +94,19 @@ EXPORT_SYMBOL(mmc_gpio_get_cd); | |||
| 103 | * @gpio: gpio number requested | 94 | * @gpio: gpio number requested |
| 104 | * | 95 | * |
| 105 | * As devm_* managed functions are used in mmc_gpio_request_ro(), client | 96 | * As devm_* managed functions are used in mmc_gpio_request_ro(), client |
| 106 | * drivers do not need to explicitly call mmc_gpio_free_ro() for freeing up, | 97 | * drivers do not need to worry about freeing up memory. |
| 107 | * if the requesting and freeing are only needed at probing and unbinding time | ||
| 108 | * for once. However, if client drivers do something special like runtime | ||
| 109 | * switching for write-protection, they are responsible for calling | ||
| 110 | * mmc_gpio_request_ro() and mmc_gpio_free_ro() as a pair on their own. | ||
| 111 | * | 98 | * |
| 112 | * Returns zero on success, else an error. | 99 | * Returns zero on success, else an error. |
| 113 | */ | 100 | */ |
| 114 | int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) | 101 | int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) |
| 115 | { | 102 | { |
| 116 | struct mmc_gpio *ctx; | 103 | struct mmc_gpio *ctx = host->slot.handler_priv; |
| 117 | int ret; | 104 | int ret; |
| 118 | 105 | ||
| 119 | if (!gpio_is_valid(gpio)) | 106 | if (!gpio_is_valid(gpio)) |
| 120 | return -EINVAL; | 107 | return -EINVAL; |
| 121 | 108 | ||
| 122 | ret = mmc_gpio_alloc(host); | 109 | ret = devm_gpio_request_one(host->parent, gpio, GPIOF_DIR_IN, |
| 123 | if (ret < 0) | ||
| 124 | return ret; | ||
| 125 | |||
| 126 | ctx = host->slot.handler_priv; | ||
| 127 | |||
| 128 | ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN, | ||
| 129 | ctx->ro_label); | 110 | ctx->ro_label); |
| 130 | if (ret < 0) | 111 | if (ret < 0) |
| 131 | return ret; | 112 | return ret; |
| @@ -156,8 +137,10 @@ void mmc_gpiod_request_cd_irq(struct mmc_host *host) | |||
| 156 | irq = -EINVAL; | 137 | irq = -EINVAL; |
| 157 | 138 | ||
| 158 | if (irq >= 0) { | 139 | if (irq >= 0) { |
| 159 | ret = devm_request_threaded_irq(&host->class_dev, irq, | 140 | if (!ctx->cd_gpio_isr) |
| 160 | NULL, mmc_gpio_cd_irqt, | 141 | ctx->cd_gpio_isr = mmc_gpio_cd_irqt; |
| 142 | ret = devm_request_threaded_irq(host->parent, irq, | ||
| 143 | NULL, ctx->cd_gpio_isr, | ||
| 161 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 144 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
| 162 | ctx->cd_label, host); | 145 | ctx->cd_label, host); |
| 163 | if (ret < 0) | 146 | if (ret < 0) |
| @@ -171,6 +154,19 @@ void mmc_gpiod_request_cd_irq(struct mmc_host *host) | |||
| 171 | } | 154 | } |
| 172 | EXPORT_SYMBOL(mmc_gpiod_request_cd_irq); | 155 | EXPORT_SYMBOL(mmc_gpiod_request_cd_irq); |
| 173 | 156 | ||
| 157 | /* Register an alternate interrupt service routine for | ||
| 158 | * the card-detect GPIO. | ||
| 159 | */ | ||
| 160 | void mmc_gpio_set_cd_isr(struct mmc_host *host, | ||
| 161 | irqreturn_t (*isr)(int irq, void *dev_id)) | ||
| 162 | { | ||
| 163 | struct mmc_gpio *ctx = host->slot.handler_priv; | ||
| 164 | |||
| 165 | WARN_ON(ctx->cd_gpio_isr); | ||
| 166 | ctx->cd_gpio_isr = isr; | ||
| 167 | } | ||
| 168 | EXPORT_SYMBOL(mmc_gpio_set_cd_isr); | ||
| 169 | |||
| 174 | /** | 170 | /** |
| 175 | * mmc_gpio_request_cd - request a gpio for card-detection | 171 | * mmc_gpio_request_cd - request a gpio for card-detection |
| 176 | * @host: mmc host | 172 | * @host: mmc host |
| @@ -178,11 +174,7 @@ EXPORT_SYMBOL(mmc_gpiod_request_cd_irq); | |||
| 178 | * @debounce: debounce time in microseconds | 174 | * @debounce: debounce time in microseconds |
| 179 | * | 175 | * |
| 180 | * As devm_* managed functions are used in mmc_gpio_request_cd(), client | 176 | * As devm_* managed functions are used in mmc_gpio_request_cd(), client |
| 181 | * drivers do not need to explicitly call mmc_gpio_free_cd() for freeing up, | 177 | * drivers do not need to worry about freeing up memory. |
| 182 | * if the requesting and freeing are only needed at probing and unbinding time | ||
| 183 | * for once. However, if client drivers do something special like runtime | ||
| 184 | * switching for card-detection, they are responsible for calling | ||
| 185 | * mmc_gpio_request_cd() and mmc_gpio_free_cd() as a pair on their own. | ||
| 186 | * | 178 | * |
| 187 | * If GPIO debouncing is desired, set the debounce parameter to a non-zero | 179 | * If GPIO debouncing is desired, set the debounce parameter to a non-zero |
| 188 | * value. The caller is responsible for ensuring that the GPIO driver associated | 180 | * value. The caller is responsible for ensuring that the GPIO driver associated |
| @@ -193,16 +185,10 @@ EXPORT_SYMBOL(mmc_gpiod_request_cd_irq); | |||
| 193 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, | 185 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, |
| 194 | unsigned int debounce) | 186 | unsigned int debounce) |
| 195 | { | 187 | { |
| 196 | struct mmc_gpio *ctx; | 188 | struct mmc_gpio *ctx = host->slot.handler_priv; |
| 197 | int ret; | 189 | int ret; |
| 198 | 190 | ||
| 199 | ret = mmc_gpio_alloc(host); | 191 | ret = devm_gpio_request_one(host->parent, gpio, GPIOF_DIR_IN, |
| 200 | if (ret < 0) | ||
| 201 | return ret; | ||
| 202 | |||
| 203 | ctx = host->slot.handler_priv; | ||
| 204 | |||
| 205 | ret = devm_gpio_request_one(&host->class_dev, gpio, GPIOF_DIR_IN, | ||
| 206 | ctx->cd_label); | 192 | ctx->cd_label); |
| 207 | if (ret < 0) | 193 | if (ret < 0) |
| 208 | /* | 194 | /* |
| @@ -226,55 +212,6 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, | |||
| 226 | EXPORT_SYMBOL(mmc_gpio_request_cd); | 212 | EXPORT_SYMBOL(mmc_gpio_request_cd); |
| 227 | 213 | ||
| 228 | /** | 214 | /** |
| 229 | * mmc_gpio_free_ro - free the write-protection gpio | ||
| 230 | * @host: mmc host | ||
| 231 | * | ||
| 232 | * It's provided only for cases that client drivers need to manually free | ||
| 233 | * up the write-protection gpio requested by mmc_gpio_request_ro(). | ||
| 234 | */ | ||
| 235 | void mmc_gpio_free_ro(struct mmc_host *host) | ||
| 236 | { | ||
| 237 | struct mmc_gpio *ctx = host->slot.handler_priv; | ||
| 238 | int gpio; | ||
| 239 | |||
| 240 | if (!ctx || !ctx->ro_gpio) | ||
| 241 | return; | ||
| 242 | |||
| 243 | gpio = desc_to_gpio(ctx->ro_gpio); | ||
| 244 | ctx->ro_gpio = NULL; | ||
| 245 | |||
| 246 | devm_gpio_free(&host->class_dev, gpio); | ||
| 247 | } | ||
| 248 | EXPORT_SYMBOL(mmc_gpio_free_ro); | ||
| 249 | |||
| 250 | /** | ||
| 251 | * mmc_gpio_free_cd - free the card-detection gpio | ||
| 252 | * @host: mmc host | ||
| 253 | * | ||
| 254 | * It's provided only for cases that client drivers need to manually free | ||
| 255 | * up the card-detection gpio requested by mmc_gpio_request_cd(). | ||
| 256 | */ | ||
| 257 | void mmc_gpio_free_cd(struct mmc_host *host) | ||
| 258 | { | ||
| 259 | struct mmc_gpio *ctx = host->slot.handler_priv; | ||
| 260 | int gpio; | ||
| 261 | |||
| 262 | if (!ctx || !ctx->cd_gpio) | ||
| 263 | return; | ||
| 264 | |||
| 265 | if (host->slot.cd_irq >= 0) { | ||
| 266 | devm_free_irq(&host->class_dev, host->slot.cd_irq, host); | ||
| 267 | host->slot.cd_irq = -EINVAL; | ||
| 268 | } | ||
| 269 | |||
| 270 | gpio = desc_to_gpio(ctx->cd_gpio); | ||
| 271 | ctx->cd_gpio = NULL; | ||
| 272 | |||
| 273 | devm_gpio_free(&host->class_dev, gpio); | ||
| 274 | } | ||
| 275 | EXPORT_SYMBOL(mmc_gpio_free_cd); | ||
| 276 | |||
| 277 | /** | ||
| 278 | * mmc_gpiod_request_cd - request a gpio descriptor for card-detection | 215 | * mmc_gpiod_request_cd - request a gpio descriptor for card-detection |
| 279 | * @host: mmc host | 216 | * @host: mmc host |
| 280 | * @con_id: function within the GPIO consumer | 217 | * @con_id: function within the GPIO consumer |
| @@ -285,8 +222,7 @@ EXPORT_SYMBOL(mmc_gpio_free_cd); | |||
| 285 | * to NULL to ignore | 222 | * to NULL to ignore |
| 286 | * | 223 | * |
| 287 | * Use this function in place of mmc_gpio_request_cd() to use the GPIO | 224 | * Use this function in place of mmc_gpio_request_cd() to use the GPIO |
| 288 | * descriptor API. Note that it is paired with mmc_gpiod_free_cd() not | 225 | * descriptor API. Note that it must be called prior to mmc_add_host() |
| 289 | * mmc_gpio_free_cd(). Note also that it must be called prior to mmc_add_host() | ||
| 290 | * otherwise the caller must also call mmc_gpiod_request_cd_irq(). | 226 | * otherwise the caller must also call mmc_gpiod_request_cd_irq(). |
| 291 | * | 227 | * |
| 292 | * Returns zero on success, else an error. | 228 | * Returns zero on success, else an error. |
| @@ -295,16 +231,10 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, | |||
| 295 | unsigned int idx, bool override_active_level, | 231 | unsigned int idx, bool override_active_level, |
| 296 | unsigned int debounce, bool *gpio_invert) | 232 | unsigned int debounce, bool *gpio_invert) |
| 297 | { | 233 | { |
| 298 | struct mmc_gpio *ctx; | 234 | struct mmc_gpio *ctx = host->slot.handler_priv; |
| 299 | struct gpio_desc *desc; | 235 | struct gpio_desc *desc; |
| 300 | int ret; | 236 | int ret; |
| 301 | 237 | ||
| 302 | ret = mmc_gpio_alloc(host); | ||
| 303 | if (ret < 0) | ||
| 304 | return ret; | ||
| 305 | |||
| 306 | ctx = host->slot.handler_priv; | ||
| 307 | |||
| 308 | if (!con_id) | 238 | if (!con_id) |
| 309 | con_id = ctx->cd_label; | 239 | con_id = ctx->cd_label; |
| 310 | 240 | ||
| @@ -339,8 +269,7 @@ EXPORT_SYMBOL(mmc_gpiod_request_cd); | |||
| 339 | * set to NULL to ignore | 269 | * set to NULL to ignore |
| 340 | * | 270 | * |
| 341 | * Use this function in place of mmc_gpio_request_ro() to use the GPIO | 271 | * Use this function in place of mmc_gpio_request_ro() to use the GPIO |
| 342 | * descriptor API. Note that it is paired with mmc_gpiod_free_ro() not | 272 | * descriptor API. |
| 343 | * mmc_gpio_free_ro(). | ||
| 344 | * | 273 | * |
| 345 | * Returns zero on success, else an error. | 274 | * Returns zero on success, else an error. |
| 346 | */ | 275 | */ |
| @@ -348,16 +277,10 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, | |||
| 348 | unsigned int idx, bool override_active_level, | 277 | unsigned int idx, bool override_active_level, |
| 349 | unsigned int debounce, bool *gpio_invert) | 278 | unsigned int debounce, bool *gpio_invert) |
| 350 | { | 279 | { |
| 351 | struct mmc_gpio *ctx; | 280 | struct mmc_gpio *ctx = host->slot.handler_priv; |
| 352 | struct gpio_desc *desc; | 281 | struct gpio_desc *desc; |
| 353 | int ret; | 282 | int ret; |
| 354 | 283 | ||
| 355 | ret = mmc_gpio_alloc(host); | ||
| 356 | if (ret < 0) | ||
| 357 | return ret; | ||
| 358 | |||
| 359 | ctx = host->slot.handler_priv; | ||
| 360 | |||
| 361 | if (!con_id) | 284 | if (!con_id) |
| 362 | con_id = ctx->ro_label; | 285 | con_id = ctx->ro_label; |
| 363 | 286 | ||
| @@ -380,28 +303,3 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, | |||
| 380 | return 0; | 303 | return 0; |
| 381 | } | 304 | } |
| 382 | EXPORT_SYMBOL(mmc_gpiod_request_ro); | 305 | EXPORT_SYMBOL(mmc_gpiod_request_ro); |
| 383 | |||
| 384 | /** | ||
| 385 | * mmc_gpiod_free_cd - free the card-detection gpio descriptor | ||
| 386 | * @host: mmc host | ||
| 387 | * | ||
| 388 | * It's provided only for cases that client drivers need to manually free | ||
| 389 | * up the card-detection gpio requested by mmc_gpiod_request_cd(). | ||
| 390 | */ | ||
| 391 | void mmc_gpiod_free_cd(struct mmc_host *host) | ||
| 392 | { | ||
| 393 | struct mmc_gpio *ctx = host->slot.handler_priv; | ||
| 394 | |||
| 395 | if (!ctx || !ctx->cd_gpio) | ||
| 396 | return; | ||
| 397 | |||
| 398 | if (host->slot.cd_irq >= 0) { | ||
| 399 | devm_free_irq(&host->class_dev, host->slot.cd_irq, host); | ||
| 400 | host->slot.cd_irq = -EINVAL; | ||
| 401 | } | ||
| 402 | |||
| 403 | devm_gpiod_put(host->parent, ctx->cd_gpio); | ||
| 404 | |||
| 405 | ctx->cd_gpio = NULL; | ||
| 406 | } | ||
| 407 | EXPORT_SYMBOL(mmc_gpiod_free_cd); | ||
diff --git a/drivers/mmc/core/slot-gpio.h b/drivers/mmc/core/slot-gpio.h new file mode 100644 index 000000000000..8c1854dc5d58 --- /dev/null +++ b/drivers/mmc/core/slot-gpio.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 Linaro Ltd | ||
| 3 | * | ||
| 4 | * Author: Ulf Hansson <ulf.hansson@linaro.org> | ||
| 5 | * | ||
| 6 | * License terms: GNU General Public License (GPL) version 2 | ||
| 7 | */ | ||
| 8 | #ifndef _MMC_CORE_SLOTGPIO_H | ||
| 9 | #define _MMC_CORE_SLOTGPIO_H | ||
| 10 | |||
| 11 | int mmc_gpio_alloc(struct mmc_host *host); | ||
| 12 | |||
| 13 | #endif | ||
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 2d6fbdd11803..61ac63a3776a 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -57,6 +57,7 @@ config MMC_SDHCI_IO_ACCESSORS | |||
| 57 | 57 | ||
| 58 | config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER | 58 | config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER |
| 59 | bool | 59 | bool |
| 60 | depends on MMC_SDHCI | ||
| 60 | select MMC_SDHCI_IO_ACCESSORS | 61 | select MMC_SDHCI_IO_ACCESSORS |
| 61 | help | 62 | help |
| 62 | This option is selected by drivers running on big endian hosts | 63 | This option is selected by drivers running on big endian hosts |
| @@ -82,6 +83,7 @@ config MMC_SDHCI_PCI | |||
| 82 | config MMC_RICOH_MMC | 83 | config MMC_RICOH_MMC |
| 83 | bool "Ricoh MMC Controller Disabler" | 84 | bool "Ricoh MMC Controller Disabler" |
| 84 | depends on MMC_SDHCI_PCI | 85 | depends on MMC_SDHCI_PCI |
| 86 | default y | ||
| 85 | help | 87 | help |
| 86 | This adds a pci quirk to disable Ricoh MMC Controller. This | 88 | This adds a pci quirk to disable Ricoh MMC Controller. This |
| 87 | proprietary controller is unnecessary because the SDHCI driver | 89 | proprietary controller is unnecessary because the SDHCI driver |
| @@ -228,6 +230,7 @@ config MMC_SDHCI_PXAV3 | |||
| 228 | tristate "Marvell MMP2 SD Host Controller support (PXAV3)" | 230 | tristate "Marvell MMP2 SD Host Controller support (PXAV3)" |
| 229 | depends on CLKDEV_LOOKUP | 231 | depends on CLKDEV_LOOKUP |
| 230 | depends on MMC_SDHCI_PLTFM | 232 | depends on MMC_SDHCI_PLTFM |
| 233 | depends on ARCH_MMP || COMPILE_TEST | ||
| 231 | default CPU_MMP2 | 234 | default CPU_MMP2 |
| 232 | help | 235 | help |
| 233 | This selects the Marvell(R) PXAV3 SD Host Controller. | 236 | This selects the Marvell(R) PXAV3 SD Host Controller. |
| @@ -240,6 +243,7 @@ config MMC_SDHCI_PXAV2 | |||
| 240 | tristate "Marvell PXA9XX SD Host Controller support (PXAV2)" | 243 | tristate "Marvell PXA9XX SD Host Controller support (PXAV2)" |
| 241 | depends on CLKDEV_LOOKUP | 244 | depends on CLKDEV_LOOKUP |
| 242 | depends on MMC_SDHCI_PLTFM | 245 | depends on MMC_SDHCI_PLTFM |
| 246 | depends on ARCH_MMP || COMPILE_TEST | ||
| 243 | default CPU_PXA910 | 247 | default CPU_PXA910 |
| 244 | help | 248 | help |
| 245 | This selects the Marvell(R) PXAV2 SD Host Controller. | 249 | This selects the Marvell(R) PXAV2 SD Host Controller. |
| @@ -292,6 +296,17 @@ config MMC_SDHCI_BCM2835 | |||
| 292 | 296 | ||
| 293 | If unsure, say N. | 297 | If unsure, say N. |
| 294 | 298 | ||
| 299 | config MMC_SDHCI_F_SDH30 | ||
| 300 | tristate "SDHCI support for Fujitsu Semiconductor F_SDH30" | ||
| 301 | depends on MMC_SDHCI_PLTFM | ||
| 302 | depends on OF | ||
| 303 | help | ||
| 304 | This selects the Secure Digital Host Controller Interface (SDHCI) | ||
| 305 | Needed by some Fujitsu SoC for MMC / SD / SDIO support. | ||
| 306 | If you have a controller with this interface, say Y or M here. | ||
| 307 | |||
| 308 | If unsure, say N. | ||
| 309 | |||
| 295 | config MMC_MOXART | 310 | config MMC_MOXART |
| 296 | tristate "MOXART SD/MMC Host Controller support" | 311 | tristate "MOXART SD/MMC Host Controller support" |
| 297 | depends on ARCH_MOXART && MMC | 312 | depends on ARCH_MOXART && MMC |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index f7b0a77cf419..6a7cfe0de332 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
| @@ -16,6 +16,7 @@ obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o | |||
| 16 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o | 16 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o |
| 17 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o | 17 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o |
| 18 | obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o | 18 | obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o |
| 19 | obj-$(CONFIG_MMC_SDHCI_F_SDH30) += sdhci_f_sdh30.o | ||
| 19 | obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o | 20 | obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o |
| 20 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 21 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
| 21 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o | 22 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o |
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 509365cb22c6..fe32948c6114 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c | |||
| @@ -21,43 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | #include "dw_mmc.h" | 22 | #include "dw_mmc.h" |
| 23 | #include "dw_mmc-pltfm.h" | 23 | #include "dw_mmc-pltfm.h" |
| 24 | 24 | #include "dw_mmc-exynos.h" | |
| 25 | #define NUM_PINS(x) (x + 2) | ||
| 26 | |||
| 27 | #define SDMMC_CLKSEL 0x09C | ||
| 28 | #define SDMMC_CLKSEL64 0x0A8 | ||
| 29 | #define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0) | ||
| 30 | #define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16) | ||
| 31 | #define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24) | ||
| 32 | #define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7) | ||
| 33 | #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ | ||
| 34 | SDMMC_CLKSEL_CCLK_DRIVE(y) | \ | ||
| 35 | SDMMC_CLKSEL_CCLK_DIVIDER(z)) | ||
| 36 | #define SDMMC_CLKSEL_WAKEUP_INT BIT(11) | ||
| 37 | |||
| 38 | #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 | ||
| 39 | #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 | ||
| 40 | |||
| 41 | /* Block number in eMMC */ | ||
| 42 | #define DWMCI_BLOCK_NUM 0xFFFFFFFF | ||
| 43 | |||
| 44 | #define SDMMC_EMMCP_BASE 0x1000 | ||
| 45 | #define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) | ||
| 46 | #define SDMMC_MPSBEGIN0 (SDMMC_EMMCP_BASE + 0x0200) | ||
| 47 | #define SDMMC_MPSEND0 (SDMMC_EMMCP_BASE + 0x0204) | ||
| 48 | #define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C) | ||
| 49 | |||
| 50 | /* SMU control bits */ | ||
| 51 | #define DWMCI_MPSCTRL_SECURE_READ_BIT BIT(7) | ||
| 52 | #define DWMCI_MPSCTRL_SECURE_WRITE_BIT BIT(6) | ||
| 53 | #define DWMCI_MPSCTRL_NON_SECURE_READ_BIT BIT(5) | ||
| 54 | #define DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4) | ||
| 55 | #define DWMCI_MPSCTRL_USE_FUSE_KEY BIT(3) | ||
| 56 | #define DWMCI_MPSCTRL_ECB_MODE BIT(2) | ||
| 57 | #define DWMCI_MPSCTRL_ENCRYPTION BIT(1) | ||
| 58 | #define DWMCI_MPSCTRL_VALID BIT(0) | ||
| 59 | |||
| 60 | #define EXYNOS_CCLKIN_MIN 50000000 /* unit: HZ */ | ||
| 61 | 25 | ||
| 62 | /* Variations in Exynos specific dw-mshc controller */ | 26 | /* Variations in Exynos specific dw-mshc controller */ |
| 63 | enum dw_mci_exynos_type { | 27 | enum dw_mci_exynos_type { |
| @@ -114,11 +78,11 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) | |||
| 114 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU || | 78 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU || |
| 115 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) { | 79 | priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) { |
| 116 | mci_writel(host, MPSBEGIN0, 0); | 80 | mci_writel(host, MPSBEGIN0, 0); |
| 117 | mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM); | 81 | mci_writel(host, MPSEND0, SDMMC_ENDING_SEC_NR_MAX); |
| 118 | mci_writel(host, MPSCTRL0, DWMCI_MPSCTRL_SECURE_WRITE_BIT | | 82 | mci_writel(host, MPSCTRL0, SDMMC_MPSCTRL_SECURE_WRITE_BIT | |
| 119 | DWMCI_MPSCTRL_NON_SECURE_READ_BIT | | 83 | SDMMC_MPSCTRL_NON_SECURE_READ_BIT | |
| 120 | DWMCI_MPSCTRL_VALID | | 84 | SDMMC_MPSCTRL_VALID | |
| 121 | DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT); | 85 | SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT); |
| 122 | } | 86 | } |
| 123 | 87 | ||
| 124 | return 0; | 88 | return 0; |
| @@ -127,9 +91,9 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) | |||
| 127 | static int dw_mci_exynos_setup_clock(struct dw_mci *host) | 91 | static int dw_mci_exynos_setup_clock(struct dw_mci *host) |
| 128 | { | 92 | { |
| 129 | struct dw_mci_exynos_priv_data *priv = host->priv; | 93 | struct dw_mci_exynos_priv_data *priv = host->priv; |
| 130 | unsigned long rate = clk_get_rate(host->ciu_clk); | ||
| 131 | 94 | ||
| 132 | host->bus_hz = rate / (priv->ciu_div + 1); | 95 | host->bus_hz /= (priv->ciu_div + 1); |
| 96 | |||
| 133 | return 0; | 97 | return 0; |
| 134 | } | 98 | } |
| 135 | 99 | ||
| @@ -232,8 +196,11 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) | |||
| 232 | mci_writel(host, CLKSEL, priv->sdr_timing); | 196 | mci_writel(host, CLKSEL, priv->sdr_timing); |
| 233 | } | 197 | } |
| 234 | 198 | ||
| 235 | /* Don't care if wanted clock is zero */ | 199 | /* |
| 236 | if (!wanted) | 200 | * Don't care if wanted clock is zero or |
| 201 | * ciu clock is unavailable | ||
| 202 | */ | ||
| 203 | if (!wanted || IS_ERR(host->ciu_clk)) | ||
| 237 | return; | 204 | return; |
| 238 | 205 | ||
| 239 | /* Guaranteed minimum frequency for cclkin */ | 206 | /* Guaranteed minimum frequency for cclkin */ |
| @@ -263,10 +230,8 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host) | |||
| 263 | int ret; | 230 | int ret; |
| 264 | 231 | ||
| 265 | priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); | 232 | priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); |
| 266 | if (!priv) { | 233 | if (!priv) |
| 267 | dev_err(host->dev, "mem alloc failed for private data\n"); | ||
| 268 | return -ENOMEM; | 234 | return -ENOMEM; |
| 269 | } | ||
| 270 | 235 | ||
| 271 | for (idx = 0; idx < ARRAY_SIZE(exynos_compat); idx++) { | 236 | for (idx = 0; idx < ARRAY_SIZE(exynos_compat); idx++) { |
| 272 | if (of_device_is_compatible(np, exynos_compat[idx].compatible)) | 237 | if (of_device_is_compatible(np, exynos_compat[idx].compatible)) |
| @@ -375,64 +340,23 @@ out: | |||
| 375 | return loc; | 340 | return loc; |
| 376 | } | 341 | } |
| 377 | 342 | ||
| 378 | static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot, u32 opcode, | 343 | static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot) |
| 379 | struct dw_mci_tuning_data *tuning_data) | ||
| 380 | { | 344 | { |
| 381 | struct dw_mci *host = slot->host; | 345 | struct dw_mci *host = slot->host; |
| 382 | struct mmc_host *mmc = slot->mmc; | 346 | struct mmc_host *mmc = slot->mmc; |
| 383 | const u8 *blk_pattern = tuning_data->blk_pattern; | ||
| 384 | u8 *blk_test; | ||
| 385 | unsigned int blksz = tuning_data->blksz; | ||
| 386 | u8 start_smpl, smpl, candiates = 0; | 347 | u8 start_smpl, smpl, candiates = 0; |
| 387 | s8 found = -1; | 348 | s8 found = -1; |
| 388 | int ret = 0; | 349 | int ret = 0; |
| 389 | 350 | ||
| 390 | blk_test = kmalloc(blksz, GFP_KERNEL); | ||
| 391 | if (!blk_test) | ||
| 392 | return -ENOMEM; | ||
| 393 | |||
| 394 | start_smpl = dw_mci_exynos_get_clksmpl(host); | 351 | start_smpl = dw_mci_exynos_get_clksmpl(host); |
| 395 | 352 | ||
| 396 | do { | 353 | do { |
| 397 | struct mmc_request mrq = {NULL}; | ||
| 398 | struct mmc_command cmd = {0}; | ||
| 399 | struct mmc_command stop = {0}; | ||
| 400 | struct mmc_data data = {0}; | ||
| 401 | struct scatterlist sg; | ||
| 402 | |||
| 403 | cmd.opcode = opcode; | ||
| 404 | cmd.arg = 0; | ||
| 405 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | ||
| 406 | |||
| 407 | stop.opcode = MMC_STOP_TRANSMISSION; | ||
| 408 | stop.arg = 0; | ||
| 409 | stop.flags = MMC_RSP_R1B | MMC_CMD_AC; | ||
| 410 | |||
| 411 | data.blksz = blksz; | ||
| 412 | data.blocks = 1; | ||
| 413 | data.flags = MMC_DATA_READ; | ||
| 414 | data.sg = &sg; | ||
| 415 | data.sg_len = 1; | ||
| 416 | |||
| 417 | sg_init_one(&sg, blk_test, blksz); | ||
| 418 | mrq.cmd = &cmd; | ||
| 419 | mrq.stop = &stop; | ||
| 420 | mrq.data = &data; | ||
| 421 | host->mrq = &mrq; | ||
| 422 | |||
| 423 | mci_writel(host, TMOUT, ~0); | 354 | mci_writel(host, TMOUT, ~0); |
| 424 | smpl = dw_mci_exynos_move_next_clksmpl(host); | 355 | smpl = dw_mci_exynos_move_next_clksmpl(host); |
| 425 | 356 | ||
| 426 | mmc_wait_for_req(mmc, &mrq); | 357 | if (!mmc_send_tuning(mmc)) |
| 358 | candiates |= (1 << smpl); | ||
| 427 | 359 | ||
| 428 | if (!cmd.error && !data.error) { | ||
| 429 | if (!memcmp(blk_pattern, blk_test, blksz)) | ||
| 430 | candiates |= (1 << smpl); | ||
| 431 | } else { | ||
| 432 | dev_dbg(host->dev, | ||
| 433 | "Tuning error: cmd.error:%d, data.error:%d\n", | ||
| 434 | cmd.error, data.error); | ||
| 435 | } | ||
| 436 | } while (start_smpl != smpl); | 360 | } while (start_smpl != smpl); |
| 437 | 361 | ||
| 438 | found = dw_mci_exynos_get_best_clksmpl(candiates); | 362 | found = dw_mci_exynos_get_best_clksmpl(candiates); |
| @@ -441,7 +365,6 @@ static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot, u32 opcode, | |||
| 441 | else | 365 | else |
| 442 | ret = -EIO; | 366 | ret = -EIO; |
| 443 | 367 | ||
| 444 | kfree(blk_test); | ||
| 445 | return ret; | 368 | return ret; |
| 446 | } | 369 | } |
| 447 | 370 | ||
| @@ -499,7 +422,7 @@ static const struct dev_pm_ops dw_mci_exynos_pmops = { | |||
| 499 | 422 | ||
| 500 | static struct platform_driver dw_mci_exynos_pltfm_driver = { | 423 | static struct platform_driver dw_mci_exynos_pltfm_driver = { |
| 501 | .probe = dw_mci_exynos_probe, | 424 | .probe = dw_mci_exynos_probe, |
| 502 | .remove = __exit_p(dw_mci_pltfm_remove), | 425 | .remove = dw_mci_pltfm_remove, |
| 503 | .driver = { | 426 | .driver = { |
| 504 | .name = "dwmmc_exynos", | 427 | .name = "dwmmc_exynos", |
| 505 | .of_match_table = dw_mci_exynos_match, | 428 | .of_match_table = dw_mci_exynos_match, |
diff --git a/drivers/mmc/host/dw_mmc-exynos.h b/drivers/mmc/host/dw_mmc-exynos.h new file mode 100644 index 000000000000..7872ce586b55 --- /dev/null +++ b/drivers/mmc/host/dw_mmc-exynos.h | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | /* | ||
| 2 | * Exynos Specific Extensions for Synopsys DW Multimedia Card Interface driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012-2014 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_EXYNOS_H_ | ||
| 13 | #define _DW_MMC_EXYNOS_H_ | ||
| 14 | |||
| 15 | /* Extended Register's Offset */ | ||
| 16 | #define SDMMC_CLKSEL 0x09C | ||
| 17 | #define SDMMC_CLKSEL64 0x0A8 | ||
| 18 | |||
| 19 | /* CLKSEL register defines */ | ||
| 20 | #define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0) | ||
| 21 | #define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16) | ||
| 22 | #define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24) | ||
| 23 | #define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7) | ||
| 24 | #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ | ||
| 25 | SDMMC_CLKSEL_CCLK_DRIVE(y) | \ | ||
| 26 | SDMMC_CLKSEL_CCLK_DIVIDER(z)) | ||
| 27 | #define SDMMC_CLKSEL_WAKEUP_INT BIT(11) | ||
| 28 | |||
| 29 | /* Protector Register */ | ||
| 30 | #define SDMMC_EMMCP_BASE 0x1000 | ||
| 31 | #define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) | ||
| 32 | #define SDMMC_MPSBEGIN0 (SDMMC_EMMCP_BASE + 0x0200) | ||
| 33 | #define SDMMC_MPSEND0 (SDMMC_EMMCP_BASE + 0x0204) | ||
| 34 | #define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C) | ||
| 35 | |||
| 36 | /* SMU control defines */ | ||
| 37 | #define SDMMC_MPSCTRL_SECURE_READ_BIT BIT(7) | ||
| 38 | #define SDMMC_MPSCTRL_SECURE_WRITE_BIT BIT(6) | ||
| 39 | #define SDMMC_MPSCTRL_NON_SECURE_READ_BIT BIT(5) | ||
| 40 | #define SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4) | ||
| 41 | #define SDMMC_MPSCTRL_USE_FUSE_KEY BIT(3) | ||
| 42 | #define SDMMC_MPSCTRL_ECB_MODE BIT(2) | ||
| 43 | #define SDMMC_MPSCTRL_ENCRYPTION BIT(1) | ||
| 44 | #define SDMMC_MPSCTRL_VALID BIT(0) | ||
| 45 | |||
| 46 | /* Maximum number of Ending sector */ | ||
| 47 | #define SDMMC_ENDING_SEC_NR_MAX 0xFFFFFFFF | ||
| 48 | |||
| 49 | /* Fixed clock divider */ | ||
| 50 | #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 | ||
| 51 | #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 | ||
| 52 | |||
| 53 | /* Minimal required clock frequency for cclkin, unit: HZ */ | ||
| 54 | #define EXYNOS_CCLKIN_MIN 50000000 | ||
| 55 | |||
| 56 | #endif /* _DW_MMC_EXYNOS_H_ */ | ||
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index 5650ac488cf3..e2a726a503ee 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c | |||
| @@ -133,7 +133,7 @@ static SIMPLE_DEV_PM_OPS(dw_mci_rockchip_pmops, | |||
| 133 | 133 | ||
| 134 | static struct platform_driver dw_mci_rockchip_pltfm_driver = { | 134 | static struct platform_driver dw_mci_rockchip_pltfm_driver = { |
| 135 | .probe = dw_mci_rockchip_probe, | 135 | .probe = dw_mci_rockchip_probe, |
| 136 | .remove = __exit_p(dw_mci_pltfm_remove), | 136 | .remove = dw_mci_pltfm_remove, |
| 137 | .driver = { | 137 | .driver = { |
| 138 | .name = "dwmmc_rockchip", | 138 | .name = "dwmmc_rockchip", |
| 139 | .of_match_table = dw_mci_rockchip_match, | 139 | .of_match_table = dw_mci_rockchip_match, |
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 67c04518ec4c..4d2e3c2e1830 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/stat.h> | 27 | #include <linux/stat.h> |
| 28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
| 29 | #include <linux/irq.h> | 29 | #include <linux/irq.h> |
| 30 | #include <linux/mmc/card.h> | ||
| 30 | #include <linux/mmc/host.h> | 31 | #include <linux/mmc/host.h> |
| 31 | #include <linux/mmc/mmc.h> | 32 | #include <linux/mmc/mmc.h> |
| 32 | #include <linux/mmc/sd.h> | 33 | #include <linux/mmc/sd.h> |
| @@ -313,7 +314,9 @@ static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd) | |||
| 313 | if (cmdr == MMC_READ_SINGLE_BLOCK || | 314 | if (cmdr == MMC_READ_SINGLE_BLOCK || |
| 314 | cmdr == MMC_READ_MULTIPLE_BLOCK || | 315 | cmdr == MMC_READ_MULTIPLE_BLOCK || |
| 315 | cmdr == MMC_WRITE_BLOCK || | 316 | cmdr == MMC_WRITE_BLOCK || |
| 316 | cmdr == MMC_WRITE_MULTIPLE_BLOCK) { | 317 | cmdr == MMC_WRITE_MULTIPLE_BLOCK || |
| 318 | cmdr == MMC_SEND_TUNING_BLOCK || | ||
| 319 | cmdr == MMC_SEND_TUNING_BLOCK_HS200) { | ||
| 317 | stop->opcode = MMC_STOP_TRANSMISSION; | 320 | stop->opcode = MMC_STOP_TRANSMISSION; |
| 318 | stop->arg = 0; | 321 | stop->arg = 0; |
| 319 | stop->flags = MMC_RSP_R1B | MMC_CMD_AC; | 322 | stop->flags = MMC_RSP_R1B | MMC_CMD_AC; |
| @@ -758,6 +761,7 @@ disable: | |||
| 758 | 761 | ||
| 759 | static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) | 762 | static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) |
| 760 | { | 763 | { |
| 764 | unsigned long irqflags; | ||
| 761 | int sg_len; | 765 | int sg_len; |
| 762 | u32 temp; | 766 | u32 temp; |
| 763 | 767 | ||
| @@ -794,9 +798,11 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) | |||
| 794 | mci_writel(host, CTRL, temp); | 798 | mci_writel(host, CTRL, temp); |
| 795 | 799 | ||
| 796 | /* Disable RX/TX IRQs, let DMA handle it */ | 800 | /* Disable RX/TX IRQs, let DMA handle it */ |
| 801 | spin_lock_irqsave(&host->irq_lock, irqflags); | ||
| 797 | temp = mci_readl(host, INTMASK); | 802 | temp = mci_readl(host, INTMASK); |
| 798 | temp &= ~(SDMMC_INT_RXDR | SDMMC_INT_TXDR); | 803 | temp &= ~(SDMMC_INT_RXDR | SDMMC_INT_TXDR); |
| 799 | mci_writel(host, INTMASK, temp); | 804 | mci_writel(host, INTMASK, temp); |
| 805 | spin_unlock_irqrestore(&host->irq_lock, irqflags); | ||
| 800 | 806 | ||
| 801 | host->dma_ops->start(host, sg_len); | 807 | host->dma_ops->start(host, sg_len); |
| 802 | 808 | ||
| @@ -805,6 +811,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) | |||
| 805 | 811 | ||
| 806 | static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) | 812 | static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) |
| 807 | { | 813 | { |
| 814 | unsigned long irqflags; | ||
| 808 | u32 temp; | 815 | u32 temp; |
| 809 | 816 | ||
| 810 | data->error = -EINPROGRESS; | 817 | data->error = -EINPROGRESS; |
| @@ -833,9 +840,12 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) | |||
| 833 | host->part_buf_count = 0; | 840 | host->part_buf_count = 0; |
| 834 | 841 | ||
| 835 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR); | 842 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR); |
| 843 | |||
| 844 | spin_lock_irqsave(&host->irq_lock, irqflags); | ||
| 836 | temp = mci_readl(host, INTMASK); | 845 | temp = mci_readl(host, INTMASK); |
| 837 | temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR; | 846 | temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR; |
| 838 | mci_writel(host, INTMASK, temp); | 847 | mci_writel(host, INTMASK, temp); |
| 848 | spin_unlock_irqrestore(&host->irq_lock, irqflags); | ||
| 839 | 849 | ||
| 840 | temp = mci_readl(host, CTRL); | 850 | temp = mci_readl(host, CTRL); |
| 841 | temp &= ~SDMMC_CTRL_DMA_ENABLE; | 851 | temp &= ~SDMMC_CTRL_DMA_ENABLE; |
| @@ -926,7 +936,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) | |||
| 926 | 936 | ||
| 927 | /* enable clock; only low power if no SDIO */ | 937 | /* enable clock; only low power if no SDIO */ |
| 928 | clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; | 938 | clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; |
| 929 | if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->sdio_id))) | 939 | if (!test_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags)) |
| 930 | clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; | 940 | clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; |
| 931 | mci_writel(host, CLKENA, clk_en_a); | 941 | mci_writel(host, CLKENA, clk_en_a); |
| 932 | 942 | ||
| @@ -1109,6 +1119,12 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 1109 | return; | 1119 | return; |
| 1110 | } | 1120 | } |
| 1111 | } | 1121 | } |
| 1122 | set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); | ||
| 1123 | regs = mci_readl(slot->host, PWREN); | ||
| 1124 | regs |= (1 << slot->id); | ||
| 1125 | mci_writel(slot->host, PWREN, regs); | ||
| 1126 | break; | ||
| 1127 | case MMC_POWER_ON: | ||
| 1112 | if (!IS_ERR(mmc->supply.vqmmc) && !slot->host->vqmmc_enabled) { | 1128 | if (!IS_ERR(mmc->supply.vqmmc) && !slot->host->vqmmc_enabled) { |
| 1113 | ret = regulator_enable(mmc->supply.vqmmc); | 1129 | ret = regulator_enable(mmc->supply.vqmmc); |
| 1114 | if (ret < 0) | 1130 | if (ret < 0) |
| @@ -1117,10 +1133,6 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 1117 | else | 1133 | else |
| 1118 | slot->host->vqmmc_enabled = true; | 1134 | slot->host->vqmmc_enabled = true; |
| 1119 | } | 1135 | } |
| 1120 | set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); | ||
| 1121 | regs = mci_readl(slot->host, PWREN); | ||
| 1122 | regs |= (1 << slot->id); | ||
| 1123 | mci_writel(slot->host, PWREN, regs); | ||
| 1124 | break; | 1136 | break; |
| 1125 | case MMC_POWER_OFF: | 1137 | case MMC_POWER_OFF: |
| 1126 | if (!IS_ERR(mmc->supply.vmmc)) | 1138 | if (!IS_ERR(mmc->supply.vmmc)) |
| @@ -1245,27 +1257,37 @@ static int dw_mci_get_cd(struct mmc_host *mmc) | |||
| 1245 | return present; | 1257 | return present; |
| 1246 | } | 1258 | } |
| 1247 | 1259 | ||
| 1248 | /* | 1260 | static void dw_mci_init_card(struct mmc_host *mmc, struct mmc_card *card) |
| 1249 | * Disable lower power mode. | ||
| 1250 | * | ||
| 1251 | * Low power mode will stop the card clock when idle. According to the | ||
| 1252 | * description of the CLKENA register we should disable low power mode | ||
| 1253 | * for SDIO cards if we need SDIO interrupts to work. | ||
| 1254 | * | ||
| 1255 | * This function is fast if low power mode is already disabled. | ||
| 1256 | */ | ||
| 1257 | static void dw_mci_disable_low_power(struct dw_mci_slot *slot) | ||
| 1258 | { | 1261 | { |
| 1262 | struct dw_mci_slot *slot = mmc_priv(mmc); | ||
| 1259 | struct dw_mci *host = slot->host; | 1263 | struct dw_mci *host = slot->host; |
| 1260 | u32 clk_en_a; | ||
| 1261 | const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; | ||
| 1262 | 1264 | ||
| 1263 | clk_en_a = mci_readl(host, CLKENA); | 1265 | /* |
| 1266 | * Low power mode will stop the card clock when idle. According to the | ||
| 1267 | * description of the CLKENA register we should disable low power mode | ||
| 1268 | * for SDIO cards if we need SDIO interrupts to work. | ||
| 1269 | */ | ||
| 1270 | if (mmc->caps & MMC_CAP_SDIO_IRQ) { | ||
| 1271 | const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; | ||
| 1272 | u32 clk_en_a_old; | ||
| 1273 | u32 clk_en_a; | ||
| 1264 | 1274 | ||
| 1265 | if (clk_en_a & clken_low_pwr) { | 1275 | clk_en_a_old = mci_readl(host, CLKENA); |
| 1266 | mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr); | 1276 | |
| 1267 | mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | | 1277 | if (card->type == MMC_TYPE_SDIO || |
| 1268 | SDMMC_CMD_PRV_DAT_WAIT, 0); | 1278 | card->type == MMC_TYPE_SD_COMBO) { |
| 1279 | set_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags); | ||
| 1280 | clk_en_a = clk_en_a_old & ~clken_low_pwr; | ||
| 1281 | } else { | ||
| 1282 | clear_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags); | ||
| 1283 | clk_en_a = clk_en_a_old | clken_low_pwr; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | if (clk_en_a != clk_en_a_old) { | ||
| 1287 | mci_writel(host, CLKENA, clk_en_a); | ||
| 1288 | mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | | ||
| 1289 | SDMMC_CMD_PRV_DAT_WAIT, 0); | ||
| 1290 | } | ||
| 1269 | } | 1291 | } |
| 1270 | } | 1292 | } |
| 1271 | 1293 | ||
| @@ -1273,25 +1295,20 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) | |||
| 1273 | { | 1295 | { |
| 1274 | struct dw_mci_slot *slot = mmc_priv(mmc); | 1296 | struct dw_mci_slot *slot = mmc_priv(mmc); |
| 1275 | struct dw_mci *host = slot->host; | 1297 | struct dw_mci *host = slot->host; |
| 1298 | unsigned long irqflags; | ||
| 1276 | u32 int_mask; | 1299 | u32 int_mask; |
| 1277 | 1300 | ||
| 1301 | spin_lock_irqsave(&host->irq_lock, irqflags); | ||
| 1302 | |||
| 1278 | /* Enable/disable Slot Specific SDIO interrupt */ | 1303 | /* Enable/disable Slot Specific SDIO interrupt */ |
| 1279 | int_mask = mci_readl(host, INTMASK); | 1304 | int_mask = mci_readl(host, INTMASK); |
| 1280 | if (enb) { | 1305 | if (enb) |
| 1281 | /* | 1306 | int_mask |= SDMMC_INT_SDIO(slot->sdio_id); |
| 1282 | * Turn off low power mode if it was enabled. This is a bit of | 1307 | else |
| 1283 | * a heavy operation and we disable / enable IRQs a lot, so | 1308 | int_mask &= ~SDMMC_INT_SDIO(slot->sdio_id); |
| 1284 | * we'll leave low power mode disabled and it will get | 1309 | mci_writel(host, INTMASK, int_mask); |
| 1285 | * re-enabled again in dw_mci_setup_bus(). | ||
| 1286 | */ | ||
| 1287 | dw_mci_disable_low_power(slot); | ||
| 1288 | 1310 | ||
| 1289 | mci_writel(host, INTMASK, | 1311 | spin_unlock_irqrestore(&host->irq_lock, irqflags); |
| 1290 | (int_mask | SDMMC_INT_SDIO(slot->sdio_id))); | ||
| 1291 | } else { | ||
| 1292 | mci_writel(host, INTMASK, | ||
| 1293 | (int_mask & ~SDMMC_INT_SDIO(slot->sdio_id))); | ||
| 1294 | } | ||
| 1295 | } | 1312 | } |
| 1296 | 1313 | ||
| 1297 | static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode) | 1314 | static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode) |
| @@ -1299,30 +1316,10 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 1299 | struct dw_mci_slot *slot = mmc_priv(mmc); | 1316 | struct dw_mci_slot *slot = mmc_priv(mmc); |
| 1300 | struct dw_mci *host = slot->host; | 1317 | struct dw_mci *host = slot->host; |
| 1301 | const struct dw_mci_drv_data *drv_data = host->drv_data; | 1318 | const struct dw_mci_drv_data *drv_data = host->drv_data; |
| 1302 | struct dw_mci_tuning_data tuning_data; | ||
| 1303 | int err = -ENOSYS; | 1319 | int err = -ENOSYS; |
| 1304 | 1320 | ||
| 1305 | if (opcode == MMC_SEND_TUNING_BLOCK_HS200) { | ||
| 1306 | if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) { | ||
| 1307 | tuning_data.blk_pattern = tuning_blk_pattern_8bit; | ||
| 1308 | tuning_data.blksz = sizeof(tuning_blk_pattern_8bit); | ||
| 1309 | } else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) { | ||
| 1310 | tuning_data.blk_pattern = tuning_blk_pattern_4bit; | ||
| 1311 | tuning_data.blksz = sizeof(tuning_blk_pattern_4bit); | ||
| 1312 | } else { | ||
| 1313 | return -EINVAL; | ||
| 1314 | } | ||
| 1315 | } else if (opcode == MMC_SEND_TUNING_BLOCK) { | ||
| 1316 | tuning_data.blk_pattern = tuning_blk_pattern_4bit; | ||
| 1317 | tuning_data.blksz = sizeof(tuning_blk_pattern_4bit); | ||
| 1318 | } else { | ||
| 1319 | dev_err(host->dev, | ||
| 1320 | "Undefined command(%d) for tuning\n", opcode); | ||
| 1321 | return -EINVAL; | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | if (drv_data && drv_data->execute_tuning) | 1321 | if (drv_data && drv_data->execute_tuning) |
| 1325 | err = drv_data->execute_tuning(slot, opcode, &tuning_data); | 1322 | err = drv_data->execute_tuning(slot); |
| 1326 | return err; | 1323 | return err; |
| 1327 | } | 1324 | } |
| 1328 | 1325 | ||
| @@ -1337,7 +1334,7 @@ static const struct mmc_host_ops dw_mci_ops = { | |||
| 1337 | .execute_tuning = dw_mci_execute_tuning, | 1334 | .execute_tuning = dw_mci_execute_tuning, |
| 1338 | .card_busy = dw_mci_card_busy, | 1335 | .card_busy = dw_mci_card_busy, |
| 1339 | .start_signal_voltage_switch = dw_mci_switch_voltage, | 1336 | .start_signal_voltage_switch = dw_mci_switch_voltage, |
| 1340 | 1337 | .init_card = dw_mci_init_card, | |
| 1341 | }; | 1338 | }; |
| 1342 | 1339 | ||
| 1343 | static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) | 1340 | static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) |
| @@ -2319,9 +2316,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
| 2319 | #ifdef CONFIG_MMC_DW_IDMAC | 2316 | #ifdef CONFIG_MMC_DW_IDMAC |
| 2320 | mmc->max_segs = host->ring_size; | 2317 | mmc->max_segs = host->ring_size; |
| 2321 | mmc->max_blk_size = 65536; | 2318 | mmc->max_blk_size = 65536; |
| 2322 | mmc->max_blk_count = host->ring_size; | ||
| 2323 | mmc->max_seg_size = 0x1000; | 2319 | mmc->max_seg_size = 0x1000; |
| 2324 | mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count; | 2320 | mmc->max_req_size = mmc->max_seg_size * host->ring_size; |
| 2321 | mmc->max_blk_count = mmc->max_req_size / 512; | ||
| 2325 | #else | 2322 | #else |
| 2326 | mmc->max_segs = 64; | 2323 | mmc->max_segs = 64; |
| 2327 | mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */ | 2324 | mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */ |
| @@ -2533,10 +2530,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | |||
| 2533 | u32 clock_frequency; | 2530 | u32 clock_frequency; |
| 2534 | 2531 | ||
| 2535 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 2532 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
| 2536 | if (!pdata) { | 2533 | if (!pdata) |
| 2537 | dev_err(dev, "could not allocate memory for pdata\n"); | ||
| 2538 | return ERR_PTR(-ENOMEM); | 2534 | return ERR_PTR(-ENOMEM); |
| 2539 | } | ||
| 2540 | 2535 | ||
| 2541 | /* find out number of slots supported */ | 2536 | /* find out number of slots supported */ |
| 2542 | if (of_property_read_u32(dev->of_node, "num-slots", | 2537 | if (of_property_read_u32(dev->of_node, "num-slots", |
| @@ -2660,6 +2655,7 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 2660 | host->quirks = host->pdata->quirks; | 2655 | host->quirks = host->pdata->quirks; |
| 2661 | 2656 | ||
| 2662 | spin_lock_init(&host->lock); | 2657 | spin_lock_init(&host->lock); |
| 2658 | spin_lock_init(&host->irq_lock); | ||
| 2663 | INIT_LIST_HEAD(&host->queue); | 2659 | INIT_LIST_HEAD(&host->queue); |
| 2664 | 2660 | ||
| 2665 | /* | 2661 | /* |
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 0d0f7a271d63..18c4afe683b8 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h | |||
| @@ -244,15 +244,11 @@ struct dw_mci_slot { | |||
| 244 | unsigned long flags; | 244 | unsigned long flags; |
| 245 | #define DW_MMC_CARD_PRESENT 0 | 245 | #define DW_MMC_CARD_PRESENT 0 |
| 246 | #define DW_MMC_CARD_NEED_INIT 1 | 246 | #define DW_MMC_CARD_NEED_INIT 1 |
| 247 | #define DW_MMC_CARD_NO_LOW_PWR 2 | ||
| 247 | int id; | 248 | int id; |
| 248 | int sdio_id; | 249 | int sdio_id; |
| 249 | }; | 250 | }; |
| 250 | 251 | ||
| 251 | struct dw_mci_tuning_data { | ||
| 252 | const u8 *blk_pattern; | ||
| 253 | unsigned int blksz; | ||
| 254 | }; | ||
| 255 | |||
| 256 | /** | 252 | /** |
| 257 | * dw_mci driver data - dw-mshc implementation specific driver data. | 253 | * dw_mci driver data - dw-mshc implementation specific driver data. |
| 258 | * @caps: mmc subsystem specified capabilities of the controller(s). | 254 | * @caps: mmc subsystem specified capabilities of the controller(s). |
| @@ -274,7 +270,6 @@ struct dw_mci_drv_data { | |||
| 274 | void (*prepare_command)(struct dw_mci *host, u32 *cmdr); | 270 | void (*prepare_command)(struct dw_mci *host, u32 *cmdr); |
| 275 | void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); | 271 | void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); |
| 276 | int (*parse_dt)(struct dw_mci *host); | 272 | int (*parse_dt)(struct dw_mci *host); |
| 277 | int (*execute_tuning)(struct dw_mci_slot *slot, u32 opcode, | 273 | int (*execute_tuning)(struct dw_mci_slot *slot); |
| 278 | struct dw_mci_tuning_data *tuning_data); | ||
| 279 | }; | 274 | }; |
| 280 | #endif /* _DW_MMC_H_ */ | 275 | #endif /* _DW_MMC_H_ */ |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 8232e9a02d40..7fe16194ebc8 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
| @@ -430,7 +430,6 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) | |||
| 430 | static void mmci_dma_setup(struct mmci_host *host) | 430 | static void mmci_dma_setup(struct mmci_host *host) |
| 431 | { | 431 | { |
| 432 | const char *rxname, *txname; | 432 | const char *rxname, *txname; |
| 433 | dma_cap_mask_t mask; | ||
| 434 | struct variant_data *variant = host->variant; | 433 | struct variant_data *variant = host->variant; |
| 435 | 434 | ||
| 436 | host->dma_rx_channel = dma_request_slave_channel(mmc_dev(host->mmc), "rx"); | 435 | host->dma_rx_channel = dma_request_slave_channel(mmc_dev(host->mmc), "rx"); |
| @@ -439,10 +438,6 @@ static void mmci_dma_setup(struct mmci_host *host) | |||
| 439 | /* initialize pre request cookie */ | 438 | /* initialize pre request cookie */ |
| 440 | host->next_data.cookie = 1; | 439 | host->next_data.cookie = 1; |
| 441 | 440 | ||
| 442 | /* Try to acquire a generic DMA engine slave channel */ | ||
| 443 | dma_cap_zero(mask); | ||
| 444 | dma_cap_set(DMA_SLAVE, mask); | ||
| 445 | |||
| 446 | /* | 441 | /* |
| 447 | * If only an RX channel is specified, the driver will | 442 | * If only an RX channel is specified, the driver will |
| 448 | * attempt to use it bidirectionally, however if it is | 443 | * attempt to use it bidirectionally, however if it is |
| @@ -1739,10 +1734,10 @@ static int mmci_probe(struct amba_device *dev, | |||
| 1739 | 1734 | ||
| 1740 | pm_runtime_set_autosuspend_delay(&dev->dev, 50); | 1735 | pm_runtime_set_autosuspend_delay(&dev->dev, 50); |
| 1741 | pm_runtime_use_autosuspend(&dev->dev); | 1736 | pm_runtime_use_autosuspend(&dev->dev); |
| 1742 | pm_runtime_put(&dev->dev); | ||
| 1743 | 1737 | ||
| 1744 | mmc_add_host(mmc); | 1738 | mmc_add_host(mmc); |
| 1745 | 1739 | ||
| 1740 | pm_runtime_put(&dev->dev); | ||
| 1746 | return 0; | 1741 | return 0; |
| 1747 | 1742 | ||
| 1748 | clk_disable: | 1743 | clk_disable: |
diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index f3e18d08e852..006f1862444b 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
| 19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| 20 | #include <linux/errno.h> | ||
| 20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
| 21 | #include <linux/blkdev.h> | 22 | #include <linux/blkdev.h> |
| 22 | #include <linux/dma-mapping.h> | 23 | #include <linux/dma-mapping.h> |
| @@ -562,7 +563,6 @@ static int moxart_probe(struct platform_device *pdev) | |||
| 562 | struct dma_slave_config cfg; | 563 | struct dma_slave_config cfg; |
| 563 | struct clk *clk; | 564 | struct clk *clk; |
| 564 | void __iomem *reg_mmc; | 565 | void __iomem *reg_mmc; |
| 565 | dma_cap_mask_t mask; | ||
| 566 | int irq, ret; | 566 | int irq, ret; |
| 567 | u32 i; | 567 | u32 i; |
| 568 | 568 | ||
| @@ -586,9 +586,8 @@ static int moxart_probe(struct platform_device *pdev) | |||
| 586 | goto out; | 586 | goto out; |
| 587 | } | 587 | } |
| 588 | 588 | ||
| 589 | clk = of_clk_get(node, 0); | 589 | clk = devm_clk_get(dev, NULL); |
| 590 | if (IS_ERR(clk)) { | 590 | if (IS_ERR(clk)) { |
| 591 | dev_err(dev, "of_clk_get failed\n"); | ||
| 592 | ret = PTR_ERR(clk); | 591 | ret = PTR_ERR(clk); |
| 593 | goto out; | 592 | goto out; |
| 594 | } | 593 | } |
| @@ -599,10 +598,9 @@ static int moxart_probe(struct platform_device *pdev) | |||
| 599 | goto out; | 598 | goto out; |
| 600 | } | 599 | } |
| 601 | 600 | ||
| 602 | mmc_of_parse(mmc); | 601 | ret = mmc_of_parse(mmc); |
| 603 | 602 | if (ret) | |
| 604 | dma_cap_zero(mask); | 603 | goto out; |
| 605 | dma_cap_set(DMA_SLAVE, mask); | ||
| 606 | 604 | ||
| 607 | host = mmc_priv(mmc); | 605 | host = mmc_priv(mmc); |
| 608 | host->mmc = mmc; | 606 | host->mmc = mmc; |
| @@ -611,8 +609,8 @@ static int moxart_probe(struct platform_device *pdev) | |||
| 611 | host->timeout = msecs_to_jiffies(1000); | 609 | host->timeout = msecs_to_jiffies(1000); |
| 612 | host->sysclk = clk_get_rate(clk); | 610 | host->sysclk = clk_get_rate(clk); |
| 613 | host->fifo_width = readl(host->base + REG_FEATURE) << 2; | 611 | host->fifo_width = readl(host->base + REG_FEATURE) << 2; |
| 614 | host->dma_chan_tx = of_dma_request_slave_channel(node, "tx"); | 612 | host->dma_chan_tx = dma_request_slave_channel_reason(dev, "tx"); |
| 615 | host->dma_chan_rx = of_dma_request_slave_channel(node, "rx"); | 613 | host->dma_chan_rx = dma_request_slave_channel_reason(dev, "rx"); |
| 616 | 614 | ||
| 617 | spin_lock_init(&host->lock); | 615 | spin_lock_init(&host->lock); |
| 618 | 616 | ||
| @@ -622,6 +620,11 @@ static int moxart_probe(struct platform_device *pdev) | |||
| 622 | mmc->ocr_avail = 0xffff00; /* Support 2.0v - 3.6v power. */ | 620 | mmc->ocr_avail = 0xffff00; /* Support 2.0v - 3.6v power. */ |
| 623 | 621 | ||
| 624 | if (IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { | 622 | if (IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { |
| 623 | if (PTR_ERR(host->dma_chan_tx) == -EPROBE_DEFER || | ||
| 624 | PTR_ERR(host->dma_chan_rx) == -EPROBE_DEFER) { | ||
| 625 | ret = -EPROBE_DEFER; | ||
| 626 | goto out; | ||
| 627 | } | ||
| 625 | dev_dbg(dev, "PIO mode transfer enabled\n"); | 628 | dev_dbg(dev, "PIO mode transfer enabled\n"); |
| 626 | host->have_dma = false; | 629 | host->have_dma = false; |
| 627 | } else { | 630 | } else { |
| @@ -700,9 +703,6 @@ static int moxart_remove(struct platform_device *pdev) | |||
| 700 | writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, | 703 | writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, |
| 701 | host->base + REG_CLOCK_CONTROL); | 704 | host->base + REG_CLOCK_CONTROL); |
| 702 | } | 705 | } |
| 703 | |||
| 704 | kfree(host); | ||
| 705 | |||
| 706 | return 0; | 706 | return 0; |
| 707 | } | 707 | } |
| 708 | 708 | ||
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 4f8618f4522d..a448498e3af2 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/of_irq.h> | 25 | #include <linux/of_irq.h> |
| 26 | #include <linux/mmc/host.h> | 26 | #include <linux/mmc/host.h> |
| 27 | #include <linux/mmc/slot-gpio.h> | 27 | #include <linux/mmc/slot-gpio.h> |
| 28 | #include <linux/pinctrl/consumer.h> | ||
| 29 | 28 | ||
| 30 | #include <asm/sizes.h> | 29 | #include <asm/sizes.h> |
| 31 | #include <asm/unaligned.h> | 30 | #include <asm/unaligned.h> |
| @@ -704,7 +703,6 @@ static int mvsd_probe(struct platform_device *pdev) | |||
| 704 | const struct mbus_dram_target_info *dram; | 703 | const struct mbus_dram_target_info *dram; |
| 705 | struct resource *r; | 704 | struct resource *r; |
| 706 | int ret, irq; | 705 | int ret, irq; |
| 707 | struct pinctrl *pinctrl; | ||
| 708 | 706 | ||
| 709 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 707 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 710 | irq = platform_get_irq(pdev, 0); | 708 | irq = platform_get_irq(pdev, 0); |
| @@ -721,10 +719,6 @@ static int mvsd_probe(struct platform_device *pdev) | |||
| 721 | host->mmc = mmc; | 719 | host->mmc = mmc; |
| 722 | host->dev = &pdev->dev; | 720 | host->dev = &pdev->dev; |
| 723 | 721 | ||
| 724 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
| 725 | if (IS_ERR(pinctrl)) | ||
| 726 | dev_warn(&pdev->dev, "no pins associated\n"); | ||
| 727 | |||
| 728 | /* | 722 | /* |
| 729 | * Some non-DT platforms do not pass a clock, and the clock | 723 | * Some non-DT platforms do not pass a clock, and the clock |
| 730 | * frequency is passed through platform_data. On DT platforms, | 724 | * frequency is passed through platform_data. On DT platforms, |
| @@ -828,8 +822,6 @@ static int mvsd_probe(struct platform_device *pdev) | |||
| 828 | 822 | ||
| 829 | out: | 823 | out: |
| 830 | if (mmc) { | 824 | if (mmc) { |
| 831 | mmc_gpio_free_cd(mmc); | ||
| 832 | mmc_gpio_free_ro(mmc); | ||
| 833 | if (!IS_ERR(host->clk)) | 825 | if (!IS_ERR(host->clk)) |
| 834 | clk_disable_unprepare(host->clk); | 826 | clk_disable_unprepare(host->clk); |
| 835 | mmc_free_host(mmc); | 827 | mmc_free_host(mmc); |
| @@ -844,8 +836,6 @@ static int mvsd_remove(struct platform_device *pdev) | |||
| 844 | 836 | ||
| 845 | struct mvsd_host *host = mmc_priv(mmc); | 837 | struct mvsd_host *host = mmc_priv(mmc); |
| 846 | 838 | ||
| 847 | mmc_gpio_free_cd(mmc); | ||
| 848 | mmc_gpio_free_ro(mmc); | ||
| 849 | mmc_remove_host(mmc); | 839 | mmc_remove_host(mmc); |
| 850 | del_timer_sync(&host->timer); | 840 | del_timer_sync(&host->timer); |
| 851 | mvsd_power_down(host); | 841 | mvsd_power_down(host); |
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 60c4ca97a727..a82411a2c024 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c | |||
| @@ -677,8 +677,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
| 677 | return 0; | 677 | return 0; |
| 678 | 678 | ||
| 679 | out_free_dma: | 679 | out_free_dma: |
| 680 | if (ssp->dmach) | 680 | dma_release_channel(ssp->dmach); |
| 681 | dma_release_channel(ssp->dmach); | ||
| 682 | out_clk_disable: | 681 | out_clk_disable: |
| 683 | clk_disable_unprepare(ssp->clk); | 682 | clk_disable_unprepare(ssp->clk); |
| 684 | out_mmc_free: | 683 | out_mmc_free: |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 7c71dcdcba8b..f84cfb01716d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/mmc/host.h> | 36 | #include <linux/mmc/host.h> |
| 37 | #include <linux/mmc/core.h> | 37 | #include <linux/mmc/core.h> |
| 38 | #include <linux/mmc/mmc.h> | 38 | #include <linux/mmc/mmc.h> |
| 39 | #include <linux/mmc/slot-gpio.h> | ||
| 39 | #include <linux/io.h> | 40 | #include <linux/io.h> |
| 40 | #include <linux/irq.h> | 41 | #include <linux/irq.h> |
| 41 | #include <linux/gpio.h> | 42 | #include <linux/gpio.h> |
| @@ -251,55 +252,24 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host); | |||
| 251 | static int omap_hsmmc_card_detect(struct device *dev) | 252 | static int omap_hsmmc_card_detect(struct device *dev) |
| 252 | { | 253 | { |
| 253 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 254 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
| 254 | struct omap_hsmmc_platform_data *mmc = host->pdata; | ||
| 255 | 255 | ||
| 256 | /* NOTE: assumes card detect signal is active-low */ | 256 | return mmc_gpio_get_cd(host->mmc); |
| 257 | return !gpio_get_value_cansleep(mmc->switch_pin); | ||
| 258 | } | 257 | } |
| 259 | 258 | ||
| 260 | static int omap_hsmmc_get_wp(struct device *dev) | 259 | static int omap_hsmmc_get_wp(struct device *dev) |
| 261 | { | 260 | { |
| 262 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 261 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
| 263 | struct omap_hsmmc_platform_data *mmc = host->pdata; | ||
| 264 | 262 | ||
| 265 | /* NOTE: assumes write protect signal is active-high */ | 263 | return mmc_gpio_get_ro(host->mmc); |
| 266 | return gpio_get_value_cansleep(mmc->gpio_wp); | ||
| 267 | } | 264 | } |
| 268 | 265 | ||
| 269 | static int omap_hsmmc_get_cover_state(struct device *dev) | 266 | static int omap_hsmmc_get_cover_state(struct device *dev) |
| 270 | { | 267 | { |
| 271 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 268 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
| 272 | struct omap_hsmmc_platform_data *mmc = host->pdata; | ||
| 273 | 269 | ||
| 274 | /* NOTE: assumes card detect signal is active-low */ | 270 | return mmc_gpio_get_cd(host->mmc); |
| 275 | return !gpio_get_value_cansleep(mmc->switch_pin); | ||
| 276 | } | 271 | } |
| 277 | 272 | ||
| 278 | #ifdef CONFIG_PM | ||
| 279 | |||
| 280 | static int omap_hsmmc_suspend_cdirq(struct device *dev) | ||
| 281 | { | ||
| 282 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | ||
| 283 | |||
| 284 | disable_irq(host->card_detect_irq); | ||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int omap_hsmmc_resume_cdirq(struct device *dev) | ||
| 289 | { | ||
| 290 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | ||
| 291 | |||
| 292 | enable_irq(host->card_detect_irq); | ||
| 293 | return 0; | ||
| 294 | } | ||
| 295 | |||
| 296 | #else | ||
| 297 | |||
| 298 | #define omap_hsmmc_suspend_cdirq NULL | ||
| 299 | #define omap_hsmmc_resume_cdirq NULL | ||
| 300 | |||
| 301 | #endif | ||
| 302 | |||
| 303 | #ifdef CONFIG_REGULATOR | 273 | #ifdef CONFIG_REGULATOR |
| 304 | 274 | ||
| 305 | static int omap_hsmmc_set_power(struct device *dev, int power_on, int vdd) | 275 | static int omap_hsmmc_set_power(struct device *dev, int power_on, int vdd) |
| @@ -464,7 +434,10 @@ static inline int omap_hsmmc_have_reg(void) | |||
| 464 | 434 | ||
| 465 | #endif | 435 | #endif |
| 466 | 436 | ||
| 467 | static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, | 437 | static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id); |
| 438 | |||
| 439 | static int omap_hsmmc_gpio_init(struct mmc_host *mmc, | ||
| 440 | struct omap_hsmmc_host *host, | ||
| 468 | struct omap_hsmmc_platform_data *pdata) | 441 | struct omap_hsmmc_platform_data *pdata) |
| 469 | { | 442 | { |
| 470 | int ret; | 443 | int ret; |
| @@ -477,46 +450,24 @@ static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, | |||
| 477 | host->card_detect = omap_hsmmc_card_detect; | 450 | host->card_detect = omap_hsmmc_card_detect; |
| 478 | host->card_detect_irq = | 451 | host->card_detect_irq = |
| 479 | gpio_to_irq(pdata->switch_pin); | 452 | gpio_to_irq(pdata->switch_pin); |
| 480 | ret = gpio_request(pdata->switch_pin, "mmc_cd"); | 453 | mmc_gpio_set_cd_isr(mmc, omap_hsmmc_detect); |
| 454 | ret = mmc_gpio_request_cd(mmc, pdata->switch_pin, 0); | ||
| 481 | if (ret) | 455 | if (ret) |
| 482 | return ret; | 456 | return ret; |
| 483 | ret = gpio_direction_input(pdata->switch_pin); | ||
| 484 | if (ret) | ||
| 485 | goto err_free_sp; | ||
| 486 | } else { | 457 | } else { |
| 487 | pdata->switch_pin = -EINVAL; | 458 | pdata->switch_pin = -EINVAL; |
| 488 | } | 459 | } |
| 489 | 460 | ||
| 490 | if (gpio_is_valid(pdata->gpio_wp)) { | 461 | if (gpio_is_valid(pdata->gpio_wp)) { |
| 491 | host->get_ro = omap_hsmmc_get_wp; | 462 | host->get_ro = omap_hsmmc_get_wp; |
| 492 | ret = gpio_request(pdata->gpio_wp, "mmc_wp"); | 463 | ret = mmc_gpio_request_ro(mmc, pdata->gpio_wp); |
| 493 | if (ret) | ||
| 494 | goto err_free_cd; | ||
| 495 | ret = gpio_direction_input(pdata->gpio_wp); | ||
| 496 | if (ret) | 464 | if (ret) |
| 497 | goto err_free_wp; | 465 | return ret; |
| 498 | } else { | 466 | } else { |
| 499 | pdata->gpio_wp = -EINVAL; | 467 | pdata->gpio_wp = -EINVAL; |
| 500 | } | 468 | } |
| 501 | 469 | ||
| 502 | return 0; | 470 | return 0; |
| 503 | |||
| 504 | err_free_wp: | ||
| 505 | gpio_free(pdata->gpio_wp); | ||
| 506 | err_free_cd: | ||
| 507 | if (gpio_is_valid(pdata->switch_pin)) | ||
| 508 | err_free_sp: | ||
| 509 | gpio_free(pdata->switch_pin); | ||
| 510 | return ret; | ||
| 511 | } | ||
| 512 | |||
| 513 | static void omap_hsmmc_gpio_free(struct omap_hsmmc_host *host, | ||
| 514 | struct omap_hsmmc_platform_data *pdata) | ||
| 515 | { | ||
| 516 | if (gpio_is_valid(pdata->gpio_wp)) | ||
| 517 | gpio_free(pdata->gpio_wp); | ||
| 518 | if (gpio_is_valid(pdata->switch_pin)) | ||
| 519 | gpio_free(pdata->switch_pin); | ||
| 520 | } | 471 | } |
| 521 | 472 | ||
| 522 | /* | 473 | /* |
| @@ -1978,13 +1929,6 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) | |||
| 1978 | { | 1929 | { |
| 1979 | struct omap_hsmmc_platform_data *pdata; | 1930 | struct omap_hsmmc_platform_data *pdata; |
| 1980 | struct device_node *np = dev->of_node; | 1931 | struct device_node *np = dev->of_node; |
| 1981 | u32 bus_width, max_freq; | ||
| 1982 | int cd_gpio, wp_gpio; | ||
| 1983 | |||
| 1984 | cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); | ||
| 1985 | wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); | ||
| 1986 | if (cd_gpio == -EPROBE_DEFER || wp_gpio == -EPROBE_DEFER) | ||
| 1987 | return ERR_PTR(-EPROBE_DEFER); | ||
| 1988 | 1932 | ||
| 1989 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 1933 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
| 1990 | if (!pdata) | 1934 | if (!pdata) |
| @@ -1993,34 +1937,20 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) | |||
| 1993 | if (of_find_property(np, "ti,dual-volt", NULL)) | 1937 | if (of_find_property(np, "ti,dual-volt", NULL)) |
| 1994 | pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; | 1938 | pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; |
| 1995 | 1939 | ||
| 1996 | pdata->switch_pin = cd_gpio; | 1940 | pdata->switch_pin = -EINVAL; |
| 1997 | pdata->gpio_wp = wp_gpio; | 1941 | pdata->gpio_wp = -EINVAL; |
| 1998 | 1942 | ||
| 1999 | if (of_find_property(np, "ti,non-removable", NULL)) { | 1943 | if (of_find_property(np, "ti,non-removable", NULL)) { |
| 2000 | pdata->nonremovable = true; | 1944 | pdata->nonremovable = true; |
| 2001 | pdata->no_regulator_off_init = true; | 1945 | pdata->no_regulator_off_init = true; |
| 2002 | } | 1946 | } |
| 2003 | of_property_read_u32(np, "bus-width", &bus_width); | ||
| 2004 | if (bus_width == 4) | ||
| 2005 | pdata->caps |= MMC_CAP_4_BIT_DATA; | ||
| 2006 | else if (bus_width == 8) | ||
| 2007 | pdata->caps |= MMC_CAP_8_BIT_DATA; | ||
| 2008 | 1947 | ||
| 2009 | if (of_find_property(np, "ti,needs-special-reset", NULL)) | 1948 | if (of_find_property(np, "ti,needs-special-reset", NULL)) |
| 2010 | pdata->features |= HSMMC_HAS_UPDATED_RESET; | 1949 | pdata->features |= HSMMC_HAS_UPDATED_RESET; |
| 2011 | 1950 | ||
| 2012 | if (!of_property_read_u32(np, "max-frequency", &max_freq)) | ||
| 2013 | pdata->max_freq = max_freq; | ||
| 2014 | |||
| 2015 | if (of_find_property(np, "ti,needs-special-hs-handling", NULL)) | 1951 | if (of_find_property(np, "ti,needs-special-hs-handling", NULL)) |
| 2016 | pdata->features |= HSMMC_HAS_HSPE_SUPPORT; | 1952 | pdata->features |= HSMMC_HAS_HSPE_SUPPORT; |
| 2017 | 1953 | ||
| 2018 | if (of_find_property(np, "keep-power-in-suspend", NULL)) | ||
| 2019 | pdata->pm_caps |= MMC_PM_KEEP_POWER; | ||
| 2020 | |||
| 2021 | if (of_find_property(np, "enable-sdio-wakeup", NULL)) | ||
| 2022 | pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; | ||
| 2023 | |||
| 2024 | return pdata; | 1954 | return pdata; |
| 2025 | } | 1955 | } |
| 2026 | #else | 1956 | #else |
| @@ -2078,6 +2008,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 2078 | goto err; | 2008 | goto err; |
| 2079 | } | 2009 | } |
| 2080 | 2010 | ||
| 2011 | ret = mmc_of_parse(mmc); | ||
| 2012 | if (ret) | ||
| 2013 | goto err1; | ||
| 2014 | |||
| 2081 | host = mmc_priv(mmc); | 2015 | host = mmc_priv(mmc); |
| 2082 | host->mmc = mmc; | 2016 | host->mmc = mmc; |
| 2083 | host->pdata = pdata; | 2017 | host->pdata = pdata; |
| @@ -2091,7 +2025,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 2091 | host->next_data.cookie = 1; | 2025 | host->next_data.cookie = 1; |
| 2092 | host->pbias_enabled = 0; | 2026 | host->pbias_enabled = 0; |
| 2093 | 2027 | ||
| 2094 | ret = omap_hsmmc_gpio_init(host, pdata); | 2028 | ret = omap_hsmmc_gpio_init(mmc, host, pdata); |
| 2095 | if (ret) | 2029 | if (ret) |
| 2096 | goto err_gpio; | 2030 | goto err_gpio; |
| 2097 | 2031 | ||
| @@ -2106,7 +2040,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 2106 | 2040 | ||
| 2107 | if (pdata->max_freq > 0) | 2041 | if (pdata->max_freq > 0) |
| 2108 | mmc->f_max = pdata->max_freq; | 2042 | mmc->f_max = pdata->max_freq; |
| 2109 | else | 2043 | else if (mmc->f_max == 0) |
| 2110 | mmc->f_max = OMAP_MMC_MAX_CLOCK; | 2044 | mmc->f_max = OMAP_MMC_MAX_CLOCK; |
| 2111 | 2045 | ||
| 2112 | spin_lock_init(&host->irq_lock); | 2046 | spin_lock_init(&host->irq_lock); |
| @@ -2160,7 +2094,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 2160 | if (mmc_pdata(host)->nonremovable) | 2094 | if (mmc_pdata(host)->nonremovable) |
| 2161 | mmc->caps |= MMC_CAP_NONREMOVABLE; | 2095 | mmc->caps |= MMC_CAP_NONREMOVABLE; |
| 2162 | 2096 | ||
| 2163 | mmc->pm_caps = mmc_pdata(host)->pm_caps; | 2097 | mmc->pm_caps |= mmc_pdata(host)->pm_caps; |
| 2164 | 2098 | ||
| 2165 | omap_hsmmc_conf_bus_power(host); | 2099 | omap_hsmmc_conf_bus_power(host); |
| 2166 | 2100 | ||
| @@ -2222,22 +2156,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 2222 | 2156 | ||
| 2223 | mmc->ocr_avail = mmc_pdata(host)->ocr_mask; | 2157 | mmc->ocr_avail = mmc_pdata(host)->ocr_mask; |
| 2224 | 2158 | ||
| 2225 | /* Request IRQ for card detect */ | ||
| 2226 | if (host->card_detect_irq) { | ||
| 2227 | ret = devm_request_threaded_irq(&pdev->dev, | ||
| 2228 | host->card_detect_irq, | ||
| 2229 | NULL, omap_hsmmc_detect, | ||
| 2230 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 2231 | mmc_hostname(mmc), host); | ||
| 2232 | if (ret) { | ||
| 2233 | dev_err(mmc_dev(host->mmc), | ||
| 2234 | "Unable to grab MMC CD IRQ\n"); | ||
| 2235 | goto err_irq_cd; | ||
| 2236 | } | ||
| 2237 | host->suspend = omap_hsmmc_suspend_cdirq; | ||
| 2238 | host->resume = omap_hsmmc_resume_cdirq; | ||
| 2239 | } | ||
| 2240 | |||
| 2241 | omap_hsmmc_disable_irq(host); | 2159 | omap_hsmmc_disable_irq(host); |
| 2242 | 2160 | ||
| 2243 | /* | 2161 | /* |
| @@ -2276,7 +2194,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 2276 | 2194 | ||
| 2277 | err_slot_name: | 2195 | err_slot_name: |
| 2278 | mmc_remove_host(mmc); | 2196 | mmc_remove_host(mmc); |
| 2279 | err_irq_cd: | ||
| 2280 | if (host->use_reg) | 2197 | if (host->use_reg) |
| 2281 | omap_hsmmc_reg_put(host); | 2198 | omap_hsmmc_reg_put(host); |
| 2282 | err_irq: | 2199 | err_irq: |
| @@ -2289,7 +2206,6 @@ err_irq: | |||
| 2289 | if (host->dbclk) | 2206 | if (host->dbclk) |
| 2290 | clk_disable_unprepare(host->dbclk); | 2207 | clk_disable_unprepare(host->dbclk); |
| 2291 | err1: | 2208 | err1: |
| 2292 | omap_hsmmc_gpio_free(host, pdata); | ||
| 2293 | err_gpio: | 2209 | err_gpio: |
| 2294 | mmc_free_host(mmc); | 2210 | mmc_free_host(mmc); |
| 2295 | err: | 2211 | err: |
| @@ -2315,32 +2231,12 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
| 2315 | if (host->dbclk) | 2231 | if (host->dbclk) |
| 2316 | clk_disable_unprepare(host->dbclk); | 2232 | clk_disable_unprepare(host->dbclk); |
| 2317 | 2233 | ||
| 2318 | omap_hsmmc_gpio_free(host, host->pdata); | ||
| 2319 | mmc_free_host(host->mmc); | 2234 | mmc_free_host(host->mmc); |
| 2320 | 2235 | ||
| 2321 | return 0; | 2236 | return 0; |
| 2322 | } | 2237 | } |
| 2323 | 2238 | ||
| 2324 | #ifdef CONFIG_PM | 2239 | #ifdef CONFIG_PM |
| 2325 | static int omap_hsmmc_prepare(struct device *dev) | ||
| 2326 | { | ||
| 2327 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | ||
| 2328 | |||
| 2329 | if (host->suspend) | ||
| 2330 | return host->suspend(dev); | ||
| 2331 | |||
| 2332 | return 0; | ||
| 2333 | } | ||
| 2334 | |||
| 2335 | static void omap_hsmmc_complete(struct device *dev) | ||
| 2336 | { | ||
| 2337 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | ||
| 2338 | |||
| 2339 | if (host->resume) | ||
| 2340 | host->resume(dev); | ||
| 2341 | |||
| 2342 | } | ||
| 2343 | |||
| 2344 | static int omap_hsmmc_suspend(struct device *dev) | 2240 | static int omap_hsmmc_suspend(struct device *dev) |
| 2345 | { | 2241 | { |
| 2346 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); | 2242 | struct omap_hsmmc_host *host = dev_get_drvdata(dev); |
| @@ -2398,8 +2294,6 @@ static int omap_hsmmc_resume(struct device *dev) | |||
| 2398 | } | 2294 | } |
| 2399 | 2295 | ||
| 2400 | #else | 2296 | #else |
| 2401 | #define omap_hsmmc_prepare NULL | ||
| 2402 | #define omap_hsmmc_complete NULL | ||
| 2403 | #define omap_hsmmc_suspend NULL | 2297 | #define omap_hsmmc_suspend NULL |
| 2404 | #define omap_hsmmc_resume NULL | 2298 | #define omap_hsmmc_resume NULL |
| 2405 | #endif | 2299 | #endif |
| @@ -2484,8 +2378,6 @@ static int omap_hsmmc_runtime_resume(struct device *dev) | |||
| 2484 | static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { | 2378 | static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { |
| 2485 | .suspend = omap_hsmmc_suspend, | 2379 | .suspend = omap_hsmmc_suspend, |
| 2486 | .resume = omap_hsmmc_resume, | 2380 | .resume = omap_hsmmc_resume, |
| 2487 | .prepare = omap_hsmmc_prepare, | ||
| 2488 | .complete = omap_hsmmc_complete, | ||
| 2489 | .runtime_suspend = omap_hsmmc_runtime_suspend, | 2381 | .runtime_suspend = omap_hsmmc_runtime_suspend, |
| 2490 | .runtime_resume = omap_hsmmc_runtime_resume, | 2382 | .runtime_resume = omap_hsmmc_runtime_resume, |
| 2491 | }; | 2383 | }; |
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index c70b602f8f1e..1d3d6c4bfdc6 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/mmc/host.h> | 28 | #include <linux/mmc/host.h> |
| 29 | #include <linux/mmc/mmc.h> | 29 | #include <linux/mmc/mmc.h> |
| 30 | #include <linux/mmc/sd.h> | 30 | #include <linux/mmc/sd.h> |
| 31 | #include <linux/mmc/sdio.h> | ||
| 31 | #include <linux/mmc/card.h> | 32 | #include <linux/mmc/card.h> |
| 32 | #include <linux/mfd/rtsx_pci.h> | 33 | #include <linux/mfd/rtsx_pci.h> |
| 33 | #include <asm/unaligned.h> | 34 | #include <asm/unaligned.h> |
| @@ -53,9 +54,9 @@ struct realtek_pci_sdmmc { | |||
| 53 | #define SDMMC_POWER_ON 1 | 54 | #define SDMMC_POWER_ON 1 |
| 54 | #define SDMMC_POWER_OFF 0 | 55 | #define SDMMC_POWER_OFF 0 |
| 55 | 56 | ||
| 56 | unsigned int sg_count; | 57 | int sg_count; |
| 57 | s32 cookie; | 58 | s32 cookie; |
| 58 | unsigned int cookie_sg_count; | 59 | int cookie_sg_count; |
| 59 | bool using_cookie; | 60 | bool using_cookie; |
| 60 | }; | 61 | }; |
| 61 | 62 | ||
| @@ -71,30 +72,83 @@ static inline void sd_clear_error(struct realtek_pci_sdmmc *host) | |||
| 71 | } | 72 | } |
| 72 | 73 | ||
| 73 | #ifdef DEBUG | 74 | #ifdef DEBUG |
| 74 | static void sd_print_debug_regs(struct realtek_pci_sdmmc *host) | 75 | static void dump_reg_range(struct realtek_pci_sdmmc *host, u16 start, u16 end) |
| 75 | { | 76 | { |
| 76 | struct rtsx_pcr *pcr = host->pcr; | 77 | u16 len = end - start + 1; |
| 77 | u16 i; | 78 | int i; |
| 78 | u8 *ptr; | 79 | u8 data[8]; |
| 80 | |||
| 81 | for (i = 0; i < len; i += 8) { | ||
| 82 | int j; | ||
| 83 | int n = min(8, len - i); | ||
| 84 | |||
| 85 | memset(&data, 0, sizeof(data)); | ||
| 86 | for (j = 0; j < n; j++) | ||
| 87 | rtsx_pci_read_register(host->pcr, start + i + j, | ||
| 88 | data + j); | ||
| 89 | dev_dbg(sdmmc_dev(host), "0x%04X(%d): %8ph\n", | ||
| 90 | start + i, n, data); | ||
| 91 | } | ||
| 92 | } | ||
| 79 | 93 | ||
| 80 | /* Print SD host internal registers */ | 94 | static void sd_print_debug_regs(struct realtek_pci_sdmmc *host) |
| 81 | rtsx_pci_init_cmd(pcr); | 95 | { |
| 82 | for (i = 0xFDA0; i <= 0xFDAE; i++) | 96 | dump_reg_range(host, 0xFDA0, 0xFDB3); |
| 83 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0); | 97 | dump_reg_range(host, 0xFD52, 0xFD69); |
| 84 | for (i = 0xFD52; i <= 0xFD69; i++) | ||
| 85 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0); | ||
| 86 | rtsx_pci_send_cmd(pcr, 100); | ||
| 87 | |||
| 88 | ptr = rtsx_pci_get_cmd_data(pcr); | ||
| 89 | for (i = 0xFDA0; i <= 0xFDAE; i++) | ||
| 90 | dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++)); | ||
| 91 | for (i = 0xFD52; i <= 0xFD69; i++) | ||
| 92 | dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++)); | ||
| 93 | } | 98 | } |
| 94 | #else | 99 | #else |
| 95 | #define sd_print_debug_regs(host) | 100 | #define sd_print_debug_regs(host) |
| 96 | #endif /* DEBUG */ | 101 | #endif /* DEBUG */ |
| 97 | 102 | ||
| 103 | static inline int sd_get_cd_int(struct realtek_pci_sdmmc *host) | ||
| 104 | { | ||
| 105 | return rtsx_pci_readl(host->pcr, RTSX_BIPR) & SD_EXIST; | ||
| 106 | } | ||
| 107 | |||
| 108 | static void sd_cmd_set_sd_cmd(struct rtsx_pcr *pcr, struct mmc_command *cmd) | ||
| 109 | { | ||
| 110 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0, 0xFF, | ||
| 111 | SD_CMD_START | cmd->opcode); | ||
| 112 | rtsx_pci_write_be32(pcr, SD_CMD1, cmd->arg); | ||
| 113 | } | ||
| 114 | |||
| 115 | static void sd_cmd_set_data_len(struct rtsx_pcr *pcr, u16 blocks, u16 blksz) | ||
| 116 | { | ||
| 117 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, blocks); | ||
| 118 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, blocks >> 8); | ||
| 119 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, blksz); | ||
| 120 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, blksz >> 8); | ||
| 121 | } | ||
| 122 | |||
| 123 | static int sd_response_type(struct mmc_command *cmd) | ||
| 124 | { | ||
| 125 | switch (mmc_resp_type(cmd)) { | ||
| 126 | case MMC_RSP_NONE: | ||
| 127 | return SD_RSP_TYPE_R0; | ||
| 128 | case MMC_RSP_R1: | ||
| 129 | return SD_RSP_TYPE_R1; | ||
| 130 | case MMC_RSP_R1 & ~MMC_RSP_CRC: | ||
| 131 | return SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7; | ||
| 132 | case MMC_RSP_R1B: | ||
| 133 | return SD_RSP_TYPE_R1b; | ||
| 134 | case MMC_RSP_R2: | ||
| 135 | return SD_RSP_TYPE_R2; | ||
| 136 | case MMC_RSP_R3: | ||
| 137 | return SD_RSP_TYPE_R3; | ||
| 138 | default: | ||
| 139 | return -EINVAL; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | static int sd_status_index(int resp_type) | ||
| 144 | { | ||
| 145 | if (resp_type == SD_RSP_TYPE_R0) | ||
| 146 | return 0; | ||
| 147 | else if (resp_type == SD_RSP_TYPE_R2) | ||
| 148 | return 16; | ||
| 149 | |||
| 150 | return 5; | ||
| 151 | } | ||
| 98 | /* | 152 | /* |
| 99 | * sd_pre_dma_transfer - do dma_map_sg() or using cookie | 153 | * sd_pre_dma_transfer - do dma_map_sg() or using cookie |
| 100 | * | 154 | * |
| @@ -166,123 +220,6 @@ static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, | |||
| 166 | data->host_cookie = 0; | 220 | data->host_cookie = 0; |
| 167 | } | 221 | } |
| 168 | 222 | ||
| 169 | static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, | ||
| 170 | u8 *buf, int buf_len, int timeout) | ||
| 171 | { | ||
| 172 | struct rtsx_pcr *pcr = host->pcr; | ||
| 173 | int err, i; | ||
| 174 | u8 trans_mode; | ||
| 175 | |||
| 176 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__, cmd[0] - 0x40); | ||
| 177 | |||
| 178 | if (!buf) | ||
| 179 | buf_len = 0; | ||
| 180 | |||
| 181 | if ((cmd[0] & 0x3F) == MMC_SEND_TUNING_BLOCK) | ||
| 182 | trans_mode = SD_TM_AUTO_TUNING; | ||
| 183 | else | ||
| 184 | trans_mode = SD_TM_NORMAL_READ; | ||
| 185 | |||
| 186 | rtsx_pci_init_cmd(pcr); | ||
| 187 | |||
| 188 | for (i = 0; i < 5; i++) | ||
| 189 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0 + i, 0xFF, cmd[i]); | ||
| 190 | |||
| 191 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); | ||
| 192 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, | ||
| 193 | 0xFF, (u8)(byte_cnt >> 8)); | ||
| 194 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); | ||
| 195 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); | ||
| 196 | |||
| 197 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, | ||
| 198 | SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | | ||
| 199 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); | ||
| 200 | if (trans_mode != SD_TM_AUTO_TUNING) | ||
| 201 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, | ||
| 202 | CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); | ||
| 203 | |||
| 204 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, | ||
| 205 | 0xFF, trans_mode | SD_TRANSFER_START); | ||
| 206 | rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, | ||
| 207 | SD_TRANSFER_END, SD_TRANSFER_END); | ||
| 208 | |||
| 209 | err = rtsx_pci_send_cmd(pcr, timeout); | ||
| 210 | if (err < 0) { | ||
| 211 | sd_print_debug_regs(host); | ||
| 212 | dev_dbg(sdmmc_dev(host), | ||
| 213 | "rtsx_pci_send_cmd fail (err = %d)\n", err); | ||
| 214 | return err; | ||
| 215 | } | ||
| 216 | |||
| 217 | if (buf && buf_len) { | ||
| 218 | err = rtsx_pci_read_ppbuf(pcr, buf, buf_len); | ||
| 219 | if (err < 0) { | ||
| 220 | dev_dbg(sdmmc_dev(host), | ||
| 221 | "rtsx_pci_read_ppbuf fail (err = %d)\n", err); | ||
| 222 | return err; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, | ||
| 230 | u8 *buf, int buf_len, int timeout) | ||
| 231 | { | ||
| 232 | struct rtsx_pcr *pcr = host->pcr; | ||
| 233 | int err, i; | ||
| 234 | u8 trans_mode; | ||
| 235 | |||
| 236 | if (!buf) | ||
| 237 | buf_len = 0; | ||
| 238 | |||
| 239 | if (buf && buf_len) { | ||
| 240 | err = rtsx_pci_write_ppbuf(pcr, buf, buf_len); | ||
| 241 | if (err < 0) { | ||
| 242 | dev_dbg(sdmmc_dev(host), | ||
| 243 | "rtsx_pci_write_ppbuf fail (err = %d)\n", err); | ||
| 244 | return err; | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | trans_mode = cmd ? SD_TM_AUTO_WRITE_2 : SD_TM_AUTO_WRITE_3; | ||
| 249 | rtsx_pci_init_cmd(pcr); | ||
| 250 | |||
| 251 | if (cmd) { | ||
| 252 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d\n", __func__, | ||
| 253 | cmd[0] - 0x40); | ||
| 254 | |||
| 255 | for (i = 0; i < 5; i++) | ||
| 256 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, | ||
| 257 | SD_CMD0 + i, 0xFF, cmd[i]); | ||
| 258 | } | ||
| 259 | |||
| 260 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt); | ||
| 261 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, | ||
| 262 | 0xFF, (u8)(byte_cnt >> 8)); | ||
| 263 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1); | ||
| 264 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0); | ||
| 265 | |||
| 266 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, | ||
| 267 | SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | | ||
| 268 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); | ||
| 269 | |||
| 270 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, | ||
| 271 | trans_mode | SD_TRANSFER_START); | ||
| 272 | rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, | ||
| 273 | SD_TRANSFER_END, SD_TRANSFER_END); | ||
| 274 | |||
| 275 | err = rtsx_pci_send_cmd(pcr, timeout); | ||
| 276 | if (err < 0) { | ||
| 277 | sd_print_debug_regs(host); | ||
| 278 | dev_dbg(sdmmc_dev(host), | ||
| 279 | "rtsx_pci_send_cmd fail (err = %d)\n", err); | ||
| 280 | return err; | ||
| 281 | } | ||
| 282 | |||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | |||
| 286 | static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | 223 | static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, |
| 287 | struct mmc_command *cmd) | 224 | struct mmc_command *cmd) |
| 288 | { | 225 | { |
| @@ -293,47 +230,18 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | |||
| 293 | int timeout = 100; | 230 | int timeout = 100; |
| 294 | int i; | 231 | int i; |
| 295 | u8 *ptr; | 232 | u8 *ptr; |
| 296 | int stat_idx = 0; | 233 | int rsp_type; |
| 297 | u8 rsp_type; | 234 | int stat_idx; |
| 298 | int rsp_len = 5; | ||
| 299 | bool clock_toggled = false; | 235 | bool clock_toggled = false; |
| 300 | 236 | ||
| 301 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", | 237 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", |
| 302 | __func__, cmd_idx, arg); | 238 | __func__, cmd_idx, arg); |
| 303 | 239 | ||
| 304 | /* Response type: | 240 | rsp_type = sd_response_type(cmd); |
| 305 | * R0 | 241 | if (rsp_type < 0) |
| 306 | * R1, R5, R6, R7 | ||
| 307 | * R1b | ||
| 308 | * R2 | ||
| 309 | * R3, R4 | ||
| 310 | */ | ||
| 311 | switch (mmc_resp_type(cmd)) { | ||
| 312 | case MMC_RSP_NONE: | ||
| 313 | rsp_type = SD_RSP_TYPE_R0; | ||
| 314 | rsp_len = 0; | ||
| 315 | break; | ||
| 316 | case MMC_RSP_R1: | ||
| 317 | rsp_type = SD_RSP_TYPE_R1; | ||
| 318 | break; | ||
| 319 | case MMC_RSP_R1 & ~MMC_RSP_CRC: | ||
| 320 | rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7; | ||
| 321 | break; | ||
| 322 | case MMC_RSP_R1B: | ||
| 323 | rsp_type = SD_RSP_TYPE_R1b; | ||
| 324 | break; | ||
| 325 | case MMC_RSP_R2: | ||
| 326 | rsp_type = SD_RSP_TYPE_R2; | ||
| 327 | rsp_len = 16; | ||
| 328 | break; | ||
| 329 | case MMC_RSP_R3: | ||
| 330 | rsp_type = SD_RSP_TYPE_R3; | ||
| 331 | break; | ||
| 332 | default: | ||
| 333 | dev_dbg(sdmmc_dev(host), "cmd->flag is not valid\n"); | ||
| 334 | err = -EINVAL; | ||
| 335 | goto out; | 242 | goto out; |
| 336 | } | 243 | |
| 244 | stat_idx = sd_status_index(rsp_type); | ||
| 337 | 245 | ||
| 338 | if (rsp_type == SD_RSP_TYPE_R1b) | 246 | if (rsp_type == SD_RSP_TYPE_R1b) |
| 339 | timeout = 3000; | 247 | timeout = 3000; |
| @@ -348,13 +256,7 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | |||
| 348 | } | 256 | } |
| 349 | 257 | ||
| 350 | rtsx_pci_init_cmd(pcr); | 258 | rtsx_pci_init_cmd(pcr); |
| 351 | 259 | sd_cmd_set_sd_cmd(pcr, cmd); | |
| 352 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx); | ||
| 353 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8)(arg >> 24)); | ||
| 354 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8)(arg >> 16)); | ||
| 355 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8)(arg >> 8)); | ||
| 356 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8)arg); | ||
| 357 | |||
| 358 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); | 260 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type); |
| 359 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, | 261 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, |
| 360 | 0x01, PINGPONG_BUFFER); | 262 | 0x01, PINGPONG_BUFFER); |
| @@ -368,12 +270,10 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | |||
| 368 | /* Read data from ping-pong buffer */ | 270 | /* Read data from ping-pong buffer */ |
| 369 | for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) | 271 | for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) |
| 370 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); | 272 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); |
| 371 | stat_idx = 16; | ||
| 372 | } else if (rsp_type != SD_RSP_TYPE_R0) { | 273 | } else if (rsp_type != SD_RSP_TYPE_R0) { |
| 373 | /* Read data from SD_CMDx registers */ | 274 | /* Read data from SD_CMDx registers */ |
| 374 | for (i = SD_CMD0; i <= SD_CMD4; i++) | 275 | for (i = SD_CMD0; i <= SD_CMD4; i++) |
| 375 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); | 276 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); |
| 376 | stat_idx = 5; | ||
| 377 | } | 277 | } |
| 378 | 278 | ||
| 379 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0); | 279 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0); |
| @@ -438,71 +338,213 @@ out: | |||
| 438 | SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); | 338 | SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); |
| 439 | } | 339 | } |
| 440 | 340 | ||
| 441 | static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) | 341 | static int sd_read_data(struct realtek_pci_sdmmc *host, struct mmc_command *cmd, |
| 342 | u16 byte_cnt, u8 *buf, int buf_len, int timeout) | ||
| 343 | { | ||
| 344 | struct rtsx_pcr *pcr = host->pcr; | ||
| 345 | int err; | ||
| 346 | u8 trans_mode; | ||
| 347 | |||
| 348 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", | ||
| 349 | __func__, cmd->opcode, cmd->arg); | ||
| 350 | |||
| 351 | if (!buf) | ||
| 352 | buf_len = 0; | ||
| 353 | |||
| 354 | if (cmd->opcode == MMC_SEND_TUNING_BLOCK) | ||
| 355 | trans_mode = SD_TM_AUTO_TUNING; | ||
| 356 | else | ||
| 357 | trans_mode = SD_TM_NORMAL_READ; | ||
| 358 | |||
| 359 | rtsx_pci_init_cmd(pcr); | ||
| 360 | sd_cmd_set_sd_cmd(pcr, cmd); | ||
| 361 | sd_cmd_set_data_len(pcr, 1, byte_cnt); | ||
| 362 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, | ||
| 363 | SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | | ||
| 364 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6); | ||
| 365 | if (trans_mode != SD_TM_AUTO_TUNING) | ||
| 366 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, | ||
| 367 | CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); | ||
| 368 | |||
| 369 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, | ||
| 370 | 0xFF, trans_mode | SD_TRANSFER_START); | ||
| 371 | rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, | ||
| 372 | SD_TRANSFER_END, SD_TRANSFER_END); | ||
| 373 | |||
| 374 | err = rtsx_pci_send_cmd(pcr, timeout); | ||
| 375 | if (err < 0) { | ||
| 376 | sd_print_debug_regs(host); | ||
| 377 | dev_dbg(sdmmc_dev(host), | ||
| 378 | "rtsx_pci_send_cmd fail (err = %d)\n", err); | ||
| 379 | return err; | ||
| 380 | } | ||
| 381 | |||
| 382 | if (buf && buf_len) { | ||
| 383 | err = rtsx_pci_read_ppbuf(pcr, buf, buf_len); | ||
| 384 | if (err < 0) { | ||
| 385 | dev_dbg(sdmmc_dev(host), | ||
| 386 | "rtsx_pci_read_ppbuf fail (err = %d)\n", err); | ||
| 387 | return err; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | static int sd_write_data(struct realtek_pci_sdmmc *host, | ||
| 395 | struct mmc_command *cmd, u16 byte_cnt, u8 *buf, int buf_len, | ||
| 396 | int timeout) | ||
| 397 | { | ||
| 398 | struct rtsx_pcr *pcr = host->pcr; | ||
| 399 | int err; | ||
| 400 | |||
| 401 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", | ||
| 402 | __func__, cmd->opcode, cmd->arg); | ||
| 403 | |||
| 404 | if (!buf) | ||
| 405 | buf_len = 0; | ||
| 406 | |||
| 407 | sd_send_cmd_get_rsp(host, cmd); | ||
| 408 | if (cmd->error) | ||
| 409 | return cmd->error; | ||
| 410 | |||
| 411 | if (buf && buf_len) { | ||
| 412 | err = rtsx_pci_write_ppbuf(pcr, buf, buf_len); | ||
| 413 | if (err < 0) { | ||
| 414 | dev_dbg(sdmmc_dev(host), | ||
| 415 | "rtsx_pci_write_ppbuf fail (err = %d)\n", err); | ||
| 416 | return err; | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 420 | rtsx_pci_init_cmd(pcr); | ||
| 421 | sd_cmd_set_data_len(pcr, 1, byte_cnt); | ||
| 422 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, | ||
| 423 | SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | | ||
| 424 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0); | ||
| 425 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, | ||
| 426 | SD_TRANSFER_START | SD_TM_AUTO_WRITE_3); | ||
| 427 | rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, | ||
| 428 | SD_TRANSFER_END, SD_TRANSFER_END); | ||
| 429 | |||
| 430 | err = rtsx_pci_send_cmd(pcr, timeout); | ||
| 431 | if (err < 0) { | ||
| 432 | sd_print_debug_regs(host); | ||
| 433 | dev_dbg(sdmmc_dev(host), | ||
| 434 | "rtsx_pci_send_cmd fail (err = %d)\n", err); | ||
| 435 | return err; | ||
| 436 | } | ||
| 437 | |||
| 438 | return 0; | ||
| 439 | } | ||
| 440 | |||
| 441 | static int sd_read_long_data(struct realtek_pci_sdmmc *host, | ||
| 442 | struct mmc_request *mrq) | ||
| 442 | { | 443 | { |
| 443 | struct rtsx_pcr *pcr = host->pcr; | 444 | struct rtsx_pcr *pcr = host->pcr; |
| 444 | struct mmc_host *mmc = host->mmc; | 445 | struct mmc_host *mmc = host->mmc; |
| 445 | struct mmc_card *card = mmc->card; | 446 | struct mmc_card *card = mmc->card; |
| 447 | struct mmc_command *cmd = mrq->cmd; | ||
| 446 | struct mmc_data *data = mrq->data; | 448 | struct mmc_data *data = mrq->data; |
| 447 | int uhs = mmc_card_uhs(card); | 449 | int uhs = mmc_card_uhs(card); |
| 448 | int read = (data->flags & MMC_DATA_READ) ? 1 : 0; | 450 | u8 cfg2 = 0; |
| 449 | u8 cfg2, trans_mode; | ||
| 450 | int err; | 451 | int err; |
| 452 | int resp_type; | ||
| 451 | size_t data_len = data->blksz * data->blocks; | 453 | size_t data_len = data->blksz * data->blocks; |
| 452 | 454 | ||
| 453 | if (read) { | 455 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", |
| 454 | cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | | 456 | __func__, cmd->opcode, cmd->arg); |
| 455 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; | 457 | |
| 456 | trans_mode = SD_TM_AUTO_READ_3; | 458 | resp_type = sd_response_type(cmd); |
| 457 | } else { | 459 | if (resp_type < 0) |
| 458 | cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | | 460 | return resp_type; |
| 459 | SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; | ||
| 460 | trans_mode = SD_TM_AUTO_WRITE_3; | ||
| 461 | } | ||
| 462 | 461 | ||
| 463 | if (!uhs) | 462 | if (!uhs) |
| 464 | cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; | 463 | cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; |
| 465 | 464 | ||
| 466 | rtsx_pci_init_cmd(pcr); | 465 | rtsx_pci_init_cmd(pcr); |
| 467 | 466 | sd_cmd_set_sd_cmd(pcr, cmd); | |
| 468 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); | 467 | sd_cmd_set_data_len(pcr, data->blocks, data->blksz); |
| 469 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); | ||
| 470 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, | ||
| 471 | 0xFF, (u8)data->blocks); | ||
| 472 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, | ||
| 473 | 0xFF, (u8)(data->blocks >> 8)); | ||
| 474 | |||
| 475 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0, | 468 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0, |
| 476 | DMA_DONE_INT, DMA_DONE_INT); | 469 | DMA_DONE_INT, DMA_DONE_INT); |
| 477 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, | 470 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, |
| 478 | 0xFF, (u8)(data_len >> 24)); | 471 | 0xFF, (u8)(data_len >> 24)); |
| 479 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, | 472 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, |
| 480 | 0xFF, (u8)(data_len >> 16)); | 473 | 0xFF, (u8)(data_len >> 16)); |
| 481 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, | 474 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, |
| 482 | 0xFF, (u8)(data_len >> 8)); | 475 | 0xFF, (u8)(data_len >> 8)); |
| 483 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)data_len); | 476 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)data_len); |
| 484 | if (read) { | 477 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, |
| 485 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, | 478 | 0x03 | DMA_PACK_SIZE_MASK, |
| 486 | 0x03 | DMA_PACK_SIZE_MASK, | 479 | DMA_DIR_FROM_CARD | DMA_EN | DMA_512); |
| 487 | DMA_DIR_FROM_CARD | DMA_EN | DMA_512); | 480 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, |
| 488 | } else { | 481 | 0x01, RING_BUFFER); |
| 489 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, | 482 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2 | resp_type); |
| 490 | 0x03 | DMA_PACK_SIZE_MASK, | 483 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, |
| 491 | DMA_DIR_TO_CARD | DMA_EN | DMA_512); | 484 | SD_TRANSFER_START | SD_TM_AUTO_READ_2); |
| 485 | rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, | ||
| 486 | SD_TRANSFER_END, SD_TRANSFER_END); | ||
| 487 | rtsx_pci_send_cmd_no_wait(pcr); | ||
| 488 | |||
| 489 | err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, 1, 10000); | ||
| 490 | if (err < 0) { | ||
| 491 | sd_print_debug_regs(host); | ||
| 492 | sd_clear_error(host); | ||
| 493 | return err; | ||
| 492 | } | 494 | } |
| 493 | 495 | ||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | static int sd_write_long_data(struct realtek_pci_sdmmc *host, | ||
| 500 | struct mmc_request *mrq) | ||
| 501 | { | ||
| 502 | struct rtsx_pcr *pcr = host->pcr; | ||
| 503 | struct mmc_host *mmc = host->mmc; | ||
| 504 | struct mmc_card *card = mmc->card; | ||
| 505 | struct mmc_command *cmd = mrq->cmd; | ||
| 506 | struct mmc_data *data = mrq->data; | ||
| 507 | int uhs = mmc_card_uhs(card); | ||
| 508 | u8 cfg2; | ||
| 509 | int err; | ||
| 510 | size_t data_len = data->blksz * data->blocks; | ||
| 511 | |||
| 512 | sd_send_cmd_get_rsp(host, cmd); | ||
| 513 | if (cmd->error) | ||
| 514 | return cmd->error; | ||
| 515 | |||
| 516 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", | ||
| 517 | __func__, cmd->opcode, cmd->arg); | ||
| 518 | |||
| 519 | cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | | ||
| 520 | SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; | ||
| 521 | |||
| 522 | if (!uhs) | ||
| 523 | cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; | ||
| 524 | |||
| 525 | rtsx_pci_init_cmd(pcr); | ||
| 526 | sd_cmd_set_data_len(pcr, data->blocks, data->blksz); | ||
| 527 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0, | ||
| 528 | DMA_DONE_INT, DMA_DONE_INT); | ||
| 529 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, | ||
| 530 | 0xFF, (u8)(data_len >> 24)); | ||
| 531 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, | ||
| 532 | 0xFF, (u8)(data_len >> 16)); | ||
| 533 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, | ||
| 534 | 0xFF, (u8)(data_len >> 8)); | ||
| 535 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)data_len); | ||
| 536 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, | ||
| 537 | 0x03 | DMA_PACK_SIZE_MASK, | ||
| 538 | DMA_DIR_TO_CARD | DMA_EN | DMA_512); | ||
| 494 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, | 539 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, |
| 495 | 0x01, RING_BUFFER); | 540 | 0x01, RING_BUFFER); |
| 496 | |||
| 497 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2); | 541 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2); |
| 498 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, | 542 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, |
| 499 | trans_mode | SD_TRANSFER_START); | 543 | SD_TRANSFER_START | SD_TM_AUTO_WRITE_3); |
| 500 | rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, | 544 | rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, |
| 501 | SD_TRANSFER_END, SD_TRANSFER_END); | 545 | SD_TRANSFER_END, SD_TRANSFER_END); |
| 502 | |||
| 503 | rtsx_pci_send_cmd_no_wait(pcr); | 546 | rtsx_pci_send_cmd_no_wait(pcr); |
| 504 | 547 | err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, 0, 10000); | |
| 505 | err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read, 10000); | ||
| 506 | if (err < 0) { | 548 | if (err < 0) { |
| 507 | sd_clear_error(host); | 549 | sd_clear_error(host); |
| 508 | return err; | 550 | return err; |
| @@ -511,6 +553,23 @@ static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) | |||
| 511 | return 0; | 553 | return 0; |
| 512 | } | 554 | } |
| 513 | 555 | ||
| 556 | static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) | ||
| 557 | { | ||
| 558 | struct mmc_data *data = mrq->data; | ||
| 559 | |||
| 560 | if (host->sg_count < 0) { | ||
| 561 | data->error = host->sg_count; | ||
| 562 | dev_dbg(sdmmc_dev(host), "%s: sg_count = %d is invalid\n", | ||
| 563 | __func__, host->sg_count); | ||
| 564 | return data->error; | ||
| 565 | } | ||
| 566 | |||
| 567 | if (data->flags & MMC_DATA_READ) | ||
| 568 | return sd_read_long_data(host, mrq); | ||
| 569 | |||
| 570 | return sd_write_long_data(host, mrq); | ||
| 571 | } | ||
| 572 | |||
| 514 | static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host) | 573 | static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host) |
| 515 | { | 574 | { |
| 516 | rtsx_pci_write_register(host->pcr, SD_CFG1, | 575 | rtsx_pci_write_register(host->pcr, SD_CFG1, |
| @@ -528,10 +587,7 @@ static void sd_normal_rw(struct realtek_pci_sdmmc *host, | |||
| 528 | { | 587 | { |
| 529 | struct mmc_command *cmd = mrq->cmd; | 588 | struct mmc_command *cmd = mrq->cmd; |
| 530 | struct mmc_data *data = mrq->data; | 589 | struct mmc_data *data = mrq->data; |
| 531 | u8 _cmd[5], *buf; | 590 | u8 *buf; |
| 532 | |||
| 533 | _cmd[0] = 0x40 | (u8)cmd->opcode; | ||
| 534 | put_unaligned_be32(cmd->arg, (u32 *)(&_cmd[1])); | ||
| 535 | 591 | ||
| 536 | buf = kzalloc(data->blksz, GFP_NOIO); | 592 | buf = kzalloc(data->blksz, GFP_NOIO); |
| 537 | if (!buf) { | 593 | if (!buf) { |
| @@ -543,7 +599,7 @@ static void sd_normal_rw(struct realtek_pci_sdmmc *host, | |||
| 543 | if (host->initial_mode) | 599 | if (host->initial_mode) |
| 544 | sd_disable_initial_mode(host); | 600 | sd_disable_initial_mode(host); |
| 545 | 601 | ||
| 546 | cmd->error = sd_read_data(host, _cmd, (u16)data->blksz, buf, | 602 | cmd->error = sd_read_data(host, cmd, (u16)data->blksz, buf, |
| 547 | data->blksz, 200); | 603 | data->blksz, 200); |
| 548 | 604 | ||
| 549 | if (host->initial_mode) | 605 | if (host->initial_mode) |
| @@ -553,7 +609,7 @@ static void sd_normal_rw(struct realtek_pci_sdmmc *host, | |||
| 553 | } else { | 609 | } else { |
| 554 | sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz); | 610 | sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz); |
| 555 | 611 | ||
| 556 | cmd->error = sd_write_data(host, _cmd, (u16)data->blksz, buf, | 612 | cmd->error = sd_write_data(host, cmd, (u16)data->blksz, buf, |
| 557 | data->blksz, 200); | 613 | data->blksz, 200); |
| 558 | } | 614 | } |
| 559 | 615 | ||
| @@ -653,14 +709,14 @@ static int sd_tuning_rx_cmd(struct realtek_pci_sdmmc *host, | |||
| 653 | u8 opcode, u8 sample_point) | 709 | u8 opcode, u8 sample_point) |
| 654 | { | 710 | { |
| 655 | int err; | 711 | int err; |
| 656 | u8 cmd[5] = {0}; | 712 | struct mmc_command cmd = {0}; |
| 657 | 713 | ||
| 658 | err = sd_change_phase(host, sample_point, true); | 714 | err = sd_change_phase(host, sample_point, true); |
| 659 | if (err < 0) | 715 | if (err < 0) |
| 660 | return err; | 716 | return err; |
| 661 | 717 | ||
| 662 | cmd[0] = 0x40 | opcode; | 718 | cmd.opcode = opcode; |
| 663 | err = sd_read_data(host, cmd, 0x40, NULL, 0, 100); | 719 | err = sd_read_data(host, &cmd, 0x40, NULL, 0, 100); |
| 664 | if (err < 0) { | 720 | if (err < 0) { |
| 665 | /* Wait till SD DATA IDLE */ | 721 | /* Wait till SD DATA IDLE */ |
| 666 | sd_wait_data_idle(host); | 722 | sd_wait_data_idle(host); |
| @@ -727,6 +783,12 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode) | |||
| 727 | return 0; | 783 | return 0; |
| 728 | } | 784 | } |
| 729 | 785 | ||
| 786 | static inline int sdio_extblock_cmd(struct mmc_command *cmd, | ||
| 787 | struct mmc_data *data) | ||
| 788 | { | ||
| 789 | return (cmd->opcode == SD_IO_RW_EXTENDED) && (data->blksz == 512); | ||
| 790 | } | ||
| 791 | |||
| 730 | static inline int sd_rw_cmd(struct mmc_command *cmd) | 792 | static inline int sd_rw_cmd(struct mmc_command *cmd) |
| 731 | { | 793 | { |
| 732 | return mmc_op_multi(cmd->opcode) || | 794 | return mmc_op_multi(cmd->opcode) || |
| @@ -748,7 +810,7 @@ static void sd_request(struct work_struct *work) | |||
| 748 | unsigned int data_size = 0; | 810 | unsigned int data_size = 0; |
| 749 | int err; | 811 | int err; |
| 750 | 812 | ||
| 751 | if (host->eject) { | 813 | if (host->eject || !sd_get_cd_int(host)) { |
| 752 | cmd->error = -ENOMEDIUM; | 814 | cmd->error = -ENOMEDIUM; |
| 753 | goto finish; | 815 | goto finish; |
| 754 | } | 816 | } |
| @@ -776,17 +838,15 @@ static void sd_request(struct work_struct *work) | |||
| 776 | if (mrq->data) | 838 | if (mrq->data) |
| 777 | data_size = data->blocks * data->blksz; | 839 | data_size = data->blocks * data->blksz; |
| 778 | 840 | ||
| 779 | if (!data_size || sd_rw_cmd(cmd)) { | 841 | if (!data_size) { |
| 780 | sd_send_cmd_get_rsp(host, cmd); | 842 | sd_send_cmd_get_rsp(host, cmd); |
| 843 | } else if (sd_rw_cmd(cmd) || sdio_extblock_cmd(cmd, data)) { | ||
| 844 | cmd->error = sd_rw_multi(host, mrq); | ||
| 845 | if (!host->using_cookie) | ||
| 846 | sdmmc_post_req(host->mmc, host->mrq, 0); | ||
| 781 | 847 | ||
| 782 | if (!cmd->error && data_size) { | 848 | if (mmc_op_multi(cmd->opcode) && mrq->stop) |
| 783 | sd_rw_multi(host, mrq); | 849 | sd_send_cmd_get_rsp(host, mrq->stop); |
| 784 | if (!host->using_cookie) | ||
| 785 | sdmmc_post_req(host->mmc, host->mrq, 0); | ||
| 786 | |||
| 787 | if (mmc_op_multi(cmd->opcode) && mrq->stop) | ||
| 788 | sd_send_cmd_get_rsp(host, mrq->stop); | ||
| 789 | } | ||
| 790 | } else { | 850 | } else { |
| 791 | sd_normal_rw(host, mrq); | 851 | sd_normal_rw(host, mrq); |
| 792 | } | 852 | } |
| @@ -801,8 +861,10 @@ static void sd_request(struct work_struct *work) | |||
| 801 | mutex_unlock(&pcr->pcr_mutex); | 861 | mutex_unlock(&pcr->pcr_mutex); |
| 802 | 862 | ||
| 803 | finish: | 863 | finish: |
| 804 | if (cmd->error) | 864 | if (cmd->error) { |
| 805 | dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); | 865 | dev_dbg(sdmmc_dev(host), "CMD %d 0x%08x error(%d)\n", |
| 866 | cmd->opcode, cmd->arg, cmd->error); | ||
| 867 | } | ||
| 806 | 868 | ||
| 807 | mutex_lock(&host->host_mutex); | 869 | mutex_lock(&host->host_mutex); |
| 808 | host->mrq = NULL; | 870 | host->mrq = NULL; |
| @@ -820,7 +882,7 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 820 | host->mrq = mrq; | 882 | host->mrq = mrq; |
| 821 | mutex_unlock(&host->host_mutex); | 883 | mutex_unlock(&host->host_mutex); |
| 822 | 884 | ||
| 823 | if (sd_rw_cmd(mrq->cmd)) | 885 | if (sd_rw_cmd(mrq->cmd) || sdio_extblock_cmd(mrq->cmd, data)) |
| 824 | host->using_cookie = sd_pre_dma_transfer(host, data, false); | 886 | host->using_cookie = sd_pre_dma_transfer(host, data, false); |
| 825 | 887 | ||
| 826 | queue_work(host->workq, &host->work); | 888 | queue_work(host->workq, &host->work); |
| @@ -1066,7 +1128,7 @@ static int sdmmc_get_cd(struct mmc_host *mmc) | |||
| 1066 | u32 val; | 1128 | u32 val; |
| 1067 | 1129 | ||
| 1068 | if (host->eject) | 1130 | if (host->eject) |
| 1069 | return -ENOMEDIUM; | 1131 | return cd; |
| 1070 | 1132 | ||
| 1071 | mutex_lock(&pcr->pcr_mutex); | 1133 | mutex_lock(&pcr->pcr_mutex); |
| 1072 | 1134 | ||
| @@ -1317,6 +1379,7 @@ static void rtsx_pci_sdmmc_card_event(struct platform_device *pdev) | |||
| 1317 | { | 1379 | { |
| 1318 | struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); | 1380 | struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); |
| 1319 | 1381 | ||
| 1382 | host->cookie = -1; | ||
| 1320 | mmc_detect_change(host->mmc, 0); | 1383 | mmc_detect_change(host->mmc, 0); |
| 1321 | } | 1384 | } |
| 1322 | 1385 | ||
| @@ -1349,6 +1412,7 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) | |||
| 1349 | host->pcr = pcr; | 1412 | host->pcr = pcr; |
| 1350 | host->mmc = mmc; | 1413 | host->mmc = mmc; |
| 1351 | host->pdev = pdev; | 1414 | host->pdev = pdev; |
| 1415 | host->cookie = -1; | ||
| 1352 | host->power_state = SDMMC_POWER_OFF; | 1416 | host->power_state = SDMMC_POWER_OFF; |
| 1353 | INIT_WORK(&host->work, sd_request); | 1417 | INIT_WORK(&host->work, sd_request); |
| 1354 | platform_set_drvdata(pdev, host); | 1418 | platform_set_drvdata(pdev, host); |
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 970314e0aac8..a45ed39d062c 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c | |||
| @@ -158,7 +158,7 @@ static int sdhci_acpi_emmc_probe_slot(struct platform_device *pdev, | |||
| 158 | 158 | ||
| 159 | host = c->host; | 159 | host = c->host; |
| 160 | 160 | ||
| 161 | /* Platform specific code during emmc proble slot goes here */ | 161 | /* Platform specific code during emmc probe slot goes here */ |
| 162 | 162 | ||
| 163 | if (hid && uid && !strcmp(hid, "80860F14") && !strcmp(uid, "1") && | 163 | if (hid && uid && !strcmp(hid, "80860F14") && !strcmp(uid, "1") && |
| 164 | sdhci_readl(host, SDHCI_CAPABILITIES) == 0x446cc8b2 && | 164 | sdhci_readl(host, SDHCI_CAPABILITIES) == 0x446cc8b2 && |
| @@ -179,7 +179,7 @@ static int sdhci_acpi_sdio_probe_slot(struct platform_device *pdev, | |||
| 179 | 179 | ||
| 180 | host = c->host; | 180 | host = c->host; |
| 181 | 181 | ||
| 182 | /* Platform specific code during emmc proble slot goes here */ | 182 | /* Platform specific code during sdio probe slot goes here */ |
| 183 | 183 | ||
| 184 | return 0; | 184 | return 0; |
| 185 | } | 185 | } |
| @@ -195,7 +195,7 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev, | |||
| 195 | 195 | ||
| 196 | host = c->host; | 196 | host = c->host; |
| 197 | 197 | ||
| 198 | /* Platform specific code during emmc proble slot goes here */ | 198 | /* Platform specific code during sd probe slot goes here */ |
| 199 | 199 | ||
| 200 | return 0; | 200 | return 0; |
| 201 | } | 201 | } |
| @@ -448,18 +448,13 @@ static int sdhci_acpi_runtime_resume(struct device *dev) | |||
| 448 | return sdhci_runtime_resume_host(c->host); | 448 | return sdhci_runtime_resume_host(c->host); |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | static int sdhci_acpi_runtime_idle(struct device *dev) | ||
| 452 | { | ||
| 453 | return 0; | ||
| 454 | } | ||
| 455 | |||
| 456 | #endif | 451 | #endif |
| 457 | 452 | ||
| 458 | static const struct dev_pm_ops sdhci_acpi_pm_ops = { | 453 | static const struct dev_pm_ops sdhci_acpi_pm_ops = { |
| 459 | .suspend = sdhci_acpi_suspend, | 454 | .suspend = sdhci_acpi_suspend, |
| 460 | .resume = sdhci_acpi_resume, | 455 | .resume = sdhci_acpi_resume, |
| 461 | SET_RUNTIME_PM_OPS(sdhci_acpi_runtime_suspend, | 456 | SET_RUNTIME_PM_OPS(sdhci_acpi_runtime_suspend, |
| 462 | sdhci_acpi_runtime_resume, sdhci_acpi_runtime_idle) | 457 | sdhci_acpi_runtime_resume, NULL) |
| 463 | }; | 458 | }; |
| 464 | 459 | ||
| 465 | static struct platform_driver sdhci_acpi_driver = { | 460 | static struct platform_driver sdhci_acpi_driver = { |
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index e7e4fbdcbfe0..34bb8f92586e 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c | |||
| @@ -254,7 +254,9 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev) | |||
| 254 | kona_dev = sdhci_pltfm_priv(pltfm_priv); | 254 | kona_dev = sdhci_pltfm_priv(pltfm_priv); |
| 255 | mutex_init(&kona_dev->write_lock); | 255 | mutex_init(&kona_dev->write_lock); |
| 256 | 256 | ||
| 257 | mmc_of_parse(host->mmc); | 257 | ret = mmc_of_parse(host->mmc); |
| 258 | if (ret) | ||
| 259 | goto err_pltfm_free; | ||
| 258 | 260 | ||
| 259 | if (!host->mmc->f_max) { | 261 | if (!host->mmc->f_max) { |
| 260 | dev_err(&pdev->dev, "Missing max-freq for SDHCI cfg\n"); | 262 | dev_err(&pdev->dev, "Missing max-freq for SDHCI cfg\n"); |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index af1f7c0f9545..10ef8244a239 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
| @@ -1080,10 +1080,10 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
| 1080 | goto disable_clk; | 1080 | goto disable_clk; |
| 1081 | 1081 | ||
| 1082 | pm_runtime_set_active(&pdev->dev); | 1082 | pm_runtime_set_active(&pdev->dev); |
| 1083 | pm_runtime_enable(&pdev->dev); | ||
| 1084 | pm_runtime_set_autosuspend_delay(&pdev->dev, 50); | 1083 | pm_runtime_set_autosuspend_delay(&pdev->dev, 50); |
| 1085 | pm_runtime_use_autosuspend(&pdev->dev); | 1084 | pm_runtime_use_autosuspend(&pdev->dev); |
| 1086 | pm_suspend_ignore_children(&pdev->dev, 1); | 1085 | pm_suspend_ignore_children(&pdev->dev, 1); |
| 1086 | pm_runtime_enable(&pdev->dev); | ||
| 1087 | 1087 | ||
| 1088 | return 0; | 1088 | return 0; |
| 1089 | 1089 | ||
| @@ -1103,16 +1103,15 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev) | |||
| 1103 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | 1103 | struct pltfm_imx_data *imx_data = pltfm_host->priv; |
| 1104 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); | 1104 | int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); |
| 1105 | 1105 | ||
| 1106 | sdhci_remove_host(host, dead); | 1106 | pm_runtime_get_sync(&pdev->dev); |
| 1107 | |||
| 1108 | pm_runtime_dont_use_autosuspend(&pdev->dev); | ||
| 1109 | pm_runtime_disable(&pdev->dev); | 1107 | pm_runtime_disable(&pdev->dev); |
| 1108 | pm_runtime_put_noidle(&pdev->dev); | ||
| 1110 | 1109 | ||
| 1111 | if (!IS_ENABLED(CONFIG_PM)) { | 1110 | sdhci_remove_host(host, dead); |
| 1112 | clk_disable_unprepare(imx_data->clk_per); | 1111 | |
| 1113 | clk_disable_unprepare(imx_data->clk_ipg); | 1112 | clk_disable_unprepare(imx_data->clk_per); |
| 1114 | clk_disable_unprepare(imx_data->clk_ahb); | 1113 | clk_disable_unprepare(imx_data->clk_ipg); |
| 1115 | } | 1114 | clk_disable_unprepare(imx_data->clk_ahb); |
| 1116 | 1115 | ||
| 1117 | sdhci_pltfm_free(pdev); | 1116 | sdhci_pltfm_free(pdev); |
| 1118 | 1117 | ||
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 8872c85c63d4..17fe02ed6672 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
| @@ -276,6 +276,14 @@ static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) | |||
| 276 | ESDHC_CTRL_BUSWIDTH_MASK, ctrl); | 276 | ESDHC_CTRL_BUSWIDTH_MASK, ctrl); |
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | static void esdhc_reset(struct sdhci_host *host, u8 mask) | ||
| 280 | { | ||
| 281 | sdhci_reset(host, mask); | ||
| 282 | |||
| 283 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); | ||
| 284 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); | ||
| 285 | } | ||
| 286 | |||
| 279 | static const struct sdhci_ops sdhci_esdhc_ops = { | 287 | static const struct sdhci_ops sdhci_esdhc_ops = { |
| 280 | .read_l = esdhc_readl, | 288 | .read_l = esdhc_readl, |
| 281 | .read_w = esdhc_readw, | 289 | .read_w = esdhc_readw, |
| @@ -290,7 +298,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = { | |||
| 290 | .platform_init = esdhc_of_platform_init, | 298 | .platform_init = esdhc_of_platform_init, |
| 291 | .adma_workaround = esdhci_of_adma_workaround, | 299 | .adma_workaround = esdhci_of_adma_workaround, |
| 292 | .set_bus_width = esdhc_pltfm_set_bus_width, | 300 | .set_bus_width = esdhc_pltfm_set_bus_width, |
| 293 | .reset = sdhci_reset, | 301 | .reset = esdhc_reset, |
| 294 | .set_uhs_signaling = sdhci_set_uhs_signaling, | 302 | .set_uhs_signaling = sdhci_set_uhs_signaling, |
| 295 | }; | 303 | }; |
| 296 | 304 | ||
| @@ -362,13 +370,19 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) | |||
| 362 | } | 370 | } |
| 363 | 371 | ||
| 364 | /* call to generic mmc_of_parse to support additional capabilities */ | 372 | /* call to generic mmc_of_parse to support additional capabilities */ |
| 365 | mmc_of_parse(host->mmc); | 373 | ret = mmc_of_parse(host->mmc); |
| 374 | if (ret) | ||
| 375 | goto err; | ||
| 376 | |||
| 366 | mmc_of_parse_voltage(np, &host->ocr_mask); | 377 | mmc_of_parse_voltage(np, &host->ocr_mask); |
| 367 | 378 | ||
| 368 | ret = sdhci_add_host(host); | 379 | ret = sdhci_add_host(host); |
| 369 | if (ret) | 380 | if (ret) |
| 370 | sdhci_pltfm_free(pdev); | 381 | goto err; |
| 371 | 382 | ||
| 383 | return 0; | ||
| 384 | err: | ||
| 385 | sdhci_pltfm_free(pdev); | ||
| 372 | return ret; | 386 | return ret; |
| 373 | } | 387 | } |
| 374 | 388 | ||
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 4f38554ce679..29eaff78238e 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -1367,11 +1367,6 @@ static int sdhci_pci_runtime_resume(struct device *dev) | |||
| 1367 | return 0; | 1367 | return 0; |
| 1368 | } | 1368 | } |
| 1369 | 1369 | ||
| 1370 | static int sdhci_pci_runtime_idle(struct device *dev) | ||
| 1371 | { | ||
| 1372 | return 0; | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | #else /* CONFIG_PM */ | 1370 | #else /* CONFIG_PM */ |
| 1376 | 1371 | ||
| 1377 | #define sdhci_pci_suspend NULL | 1372 | #define sdhci_pci_suspend NULL |
| @@ -1383,7 +1378,7 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = { | |||
| 1383 | .suspend = sdhci_pci_suspend, | 1378 | .suspend = sdhci_pci_suspend, |
| 1384 | .resume = sdhci_pci_resume, | 1379 | .resume = sdhci_pci_resume, |
| 1385 | SET_RUNTIME_PM_OPS(sdhci_pci_runtime_suspend, | 1380 | SET_RUNTIME_PM_OPS(sdhci_pci_runtime_suspend, |
| 1386 | sdhci_pci_runtime_resume, sdhci_pci_runtime_idle) | 1381 | sdhci_pci_runtime_resume, NULL) |
| 1387 | }; | 1382 | }; |
| 1388 | 1383 | ||
| 1389 | /*****************************************************************************\ | 1384 | /*****************************************************************************\ |
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index ca3424e7ef71..b5103a247bc1 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c | |||
| @@ -62,6 +62,7 @@ struct sdhci_pxa { | |||
| 62 | struct clk *clk_core; | 62 | struct clk *clk_core; |
| 63 | struct clk *clk_io; | 63 | struct clk *clk_io; |
| 64 | u8 power_mode; | 64 | u8 power_mode; |
| 65 | void __iomem *sdio3_conf_reg; | ||
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 67 | /* | 68 | /* |
| @@ -72,6 +73,14 @@ struct sdhci_pxa { | |||
| 72 | #define SDHCI_WINDOW_BASE(i) (0x84 + ((i) << 3)) | 73 | #define SDHCI_WINDOW_BASE(i) (0x84 + ((i) << 3)) |
| 73 | #define SDHCI_MAX_WIN_NUM 8 | 74 | #define SDHCI_MAX_WIN_NUM 8 |
| 74 | 75 | ||
| 76 | /* | ||
| 77 | * Fields below belong to SDIO3 Configuration Register (third register | ||
| 78 | * region for the Armada 38x flavor) | ||
| 79 | */ | ||
| 80 | |||
| 81 | #define SDIO3_CONF_CLK_INV BIT(0) | ||
| 82 | #define SDIO3_CONF_SD_FB_CLK BIT(2) | ||
| 83 | |||
| 75 | static int mv_conf_mbus_windows(struct platform_device *pdev, | 84 | static int mv_conf_mbus_windows(struct platform_device *pdev, |
| 76 | const struct mbus_dram_target_info *dram) | 85 | const struct mbus_dram_target_info *dram) |
| 77 | { | 86 | { |
| @@ -118,6 +127,51 @@ static int mv_conf_mbus_windows(struct platform_device *pdev, | |||
| 118 | return 0; | 127 | return 0; |
| 119 | } | 128 | } |
| 120 | 129 | ||
| 130 | static int armada_38x_quirks(struct platform_device *pdev, | ||
| 131 | struct sdhci_host *host) | ||
| 132 | { | ||
| 133 | struct device_node *np = pdev->dev.of_node; | ||
| 134 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 135 | struct sdhci_pxa *pxa = pltfm_host->priv; | ||
| 136 | struct resource *res; | ||
| 137 | |||
| 138 | host->quirks |= SDHCI_QUIRK_MISSING_CAPS; | ||
| 139 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
| 140 | "conf-sdio3"); | ||
| 141 | if (res) { | ||
| 142 | pxa->sdio3_conf_reg = devm_ioremap_resource(&pdev->dev, res); | ||
| 143 | if (IS_ERR(pxa->sdio3_conf_reg)) | ||
| 144 | return PTR_ERR(pxa->sdio3_conf_reg); | ||
| 145 | } else { | ||
| 146 | /* | ||
| 147 | * According to erratum 'FE-2946959' both SDR50 and DDR50 | ||
| 148 | * modes require specific clock adjustments in SDIO3 | ||
| 149 | * Configuration register, if the adjustment is not done, | ||
| 150 | * remove them from the capabilities. | ||
| 151 | */ | ||
| 152 | host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); | ||
| 153 | host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); | ||
| 154 | |||
| 155 | dev_warn(&pdev->dev, "conf-sdio3 register not found: disabling SDR50 and DDR50 modes.\nConsider updating your dtb\n"); | ||
| 156 | } | ||
| 157 | |||
| 158 | /* | ||
| 159 | * According to erratum 'ERR-7878951' Armada 38x SDHCI | ||
| 160 | * controller has different capabilities than the ones shown | ||
| 161 | * in its registers | ||
| 162 | */ | ||
| 163 | host->caps = sdhci_readl(host, SDHCI_CAPABILITIES); | ||
| 164 | if (of_property_read_bool(np, "no-1-8-v")) { | ||
| 165 | host->caps &= ~SDHCI_CAN_VDD_180; | ||
| 166 | host->mmc->caps &= ~MMC_CAP_1_8V_DDR; | ||
| 167 | } else { | ||
| 168 | host->caps &= ~SDHCI_CAN_VDD_330; | ||
| 169 | } | ||
| 170 | host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_USE_SDR50_TUNING); | ||
| 171 | |||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 121 | static void pxav3_reset(struct sdhci_host *host, u8 mask) | 175 | static void pxav3_reset(struct sdhci_host *host, u8 mask) |
| 122 | { | 176 | { |
| 123 | struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); | 177 | struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); |
| @@ -194,6 +248,8 @@ static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode) | |||
| 194 | 248 | ||
| 195 | static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) | 249 | static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) |
| 196 | { | 250 | { |
| 251 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 252 | struct sdhci_pxa *pxa = pltfm_host->priv; | ||
| 197 | u16 ctrl_2; | 253 | u16 ctrl_2; |
| 198 | 254 | ||
| 199 | /* | 255 | /* |
| @@ -223,6 +279,24 @@ static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) | |||
| 223 | break; | 279 | break; |
| 224 | } | 280 | } |
| 225 | 281 | ||
| 282 | /* | ||
| 283 | * Update SDIO3 Configuration register according to erratum | ||
| 284 | * FE-2946959 | ||
| 285 | */ | ||
| 286 | if (pxa->sdio3_conf_reg) { | ||
| 287 | u8 reg_val = readb(pxa->sdio3_conf_reg); | ||
| 288 | |||
| 289 | if (uhs == MMC_TIMING_UHS_SDR50 || | ||
| 290 | uhs == MMC_TIMING_UHS_DDR50) { | ||
| 291 | reg_val &= ~SDIO3_CONF_CLK_INV; | ||
| 292 | reg_val |= SDIO3_CONF_SD_FB_CLK; | ||
| 293 | } else { | ||
| 294 | reg_val |= SDIO3_CONF_CLK_INV; | ||
| 295 | reg_val &= ~SDIO3_CONF_SD_FB_CLK; | ||
| 296 | } | ||
| 297 | writeb(reg_val, pxa->sdio3_conf_reg); | ||
| 298 | } | ||
| 299 | |||
| 226 | sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); | 300 | sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); |
| 227 | dev_dbg(mmc_dev(host->mmc), | 301 | dev_dbg(mmc_dev(host->mmc), |
| 228 | "%s uhs = %d, ctrl_2 = %04X\n", | 302 | "%s uhs = %d, ctrl_2 = %04X\n", |
| @@ -268,8 +342,8 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) | |||
| 268 | if (!pdata) | 342 | if (!pdata) |
| 269 | return NULL; | 343 | return NULL; |
| 270 | 344 | ||
| 271 | of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles); | 345 | if (!of_property_read_u32(np, "mrvl,clk-delay-cycles", |
| 272 | if (clk_delay_cycles > 0) | 346 | &clk_delay_cycles)) |
| 273 | pdata->clk_delay_cycles = clk_delay_cycles; | 347 | pdata->clk_delay_cycles = clk_delay_cycles; |
| 274 | 348 | ||
| 275 | return pdata; | 349 | return pdata; |
| @@ -318,15 +392,18 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 318 | if (!IS_ERR(pxa->clk_core)) | 392 | if (!IS_ERR(pxa->clk_core)) |
| 319 | clk_prepare_enable(pxa->clk_core); | 393 | clk_prepare_enable(pxa->clk_core); |
| 320 | 394 | ||
| 395 | /* enable 1/8V DDR capable */ | ||
| 396 | host->mmc->caps |= MMC_CAP_1_8V_DDR; | ||
| 397 | |||
| 321 | if (of_device_is_compatible(np, "marvell,armada-380-sdhci")) { | 398 | if (of_device_is_compatible(np, "marvell,armada-380-sdhci")) { |
| 399 | ret = armada_38x_quirks(pdev, host); | ||
| 400 | if (ret < 0) | ||
| 401 | goto err_clk_get; | ||
| 322 | ret = mv_conf_mbus_windows(pdev, mv_mbus_dram_info()); | 402 | ret = mv_conf_mbus_windows(pdev, mv_mbus_dram_info()); |
| 323 | if (ret < 0) | 403 | if (ret < 0) |
| 324 | goto err_mbus_win; | 404 | goto err_mbus_win; |
| 325 | } | 405 | } |
| 326 | 406 | ||
| 327 | /* enable 1/8V DDR capable */ | ||
| 328 | host->mmc->caps |= MMC_CAP_1_8V_DDR; | ||
| 329 | |||
| 330 | match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev); | 407 | match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev); |
| 331 | if (match) { | 408 | if (match) { |
| 332 | ret = mmc_of_parse(host->mmc); | 409 | ret = mmc_of_parse(host->mmc); |
| @@ -365,10 +442,11 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 365 | } | 442 | } |
| 366 | } | 443 | } |
| 367 | 444 | ||
| 368 | pm_runtime_enable(&pdev->dev); | 445 | pm_runtime_get_noresume(&pdev->dev); |
| 369 | pm_runtime_get_sync(&pdev->dev); | 446 | pm_runtime_set_active(&pdev->dev); |
| 370 | pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS); | 447 | pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS); |
| 371 | pm_runtime_use_autosuspend(&pdev->dev); | 448 | pm_runtime_use_autosuspend(&pdev->dev); |
| 449 | pm_runtime_enable(&pdev->dev); | ||
| 372 | pm_suspend_ignore_children(&pdev->dev, 1); | 450 | pm_suspend_ignore_children(&pdev->dev, 1); |
| 373 | 451 | ||
| 374 | ret = sdhci_add_host(host); | 452 | ret = sdhci_add_host(host); |
| @@ -391,14 +469,13 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 391 | return 0; | 469 | return 0; |
| 392 | 470 | ||
| 393 | err_add_host: | 471 | err_add_host: |
| 394 | pm_runtime_put_sync(&pdev->dev); | ||
| 395 | pm_runtime_disable(&pdev->dev); | 472 | pm_runtime_disable(&pdev->dev); |
| 473 | pm_runtime_put_noidle(&pdev->dev); | ||
| 396 | err_of_parse: | 474 | err_of_parse: |
| 397 | err_cd_req: | 475 | err_cd_req: |
| 398 | err_mbus_win: | 476 | err_mbus_win: |
| 399 | clk_disable_unprepare(pxa->clk_io); | 477 | clk_disable_unprepare(pxa->clk_io); |
| 400 | if (!IS_ERR(pxa->clk_core)) | 478 | clk_disable_unprepare(pxa->clk_core); |
| 401 | clk_disable_unprepare(pxa->clk_core); | ||
| 402 | err_clk_get: | 479 | err_clk_get: |
| 403 | sdhci_pltfm_free(pdev); | 480 | sdhci_pltfm_free(pdev); |
| 404 | return ret; | 481 | return ret; |
| @@ -411,12 +488,13 @@ static int sdhci_pxav3_remove(struct platform_device *pdev) | |||
| 411 | struct sdhci_pxa *pxa = pltfm_host->priv; | 488 | struct sdhci_pxa *pxa = pltfm_host->priv; |
| 412 | 489 | ||
| 413 | pm_runtime_get_sync(&pdev->dev); | 490 | pm_runtime_get_sync(&pdev->dev); |
| 414 | sdhci_remove_host(host, 1); | ||
| 415 | pm_runtime_disable(&pdev->dev); | 491 | pm_runtime_disable(&pdev->dev); |
| 492 | pm_runtime_put_noidle(&pdev->dev); | ||
| 493 | |||
| 494 | sdhci_remove_host(host, 1); | ||
| 416 | 495 | ||
| 417 | clk_disable_unprepare(pxa->clk_io); | 496 | clk_disable_unprepare(pxa->clk_io); |
| 418 | if (!IS_ERR(pxa->clk_core)) | 497 | clk_disable_unprepare(pxa->clk_core); |
| 419 | clk_disable_unprepare(pxa->clk_core); | ||
| 420 | 498 | ||
| 421 | sdhci_pltfm_free(pdev); | 499 | sdhci_pltfm_free(pdev); |
| 422 | 500 | ||
| @@ -457,11 +535,11 @@ static int sdhci_pxav3_runtime_suspend(struct device *dev) | |||
| 457 | struct sdhci_host *host = dev_get_drvdata(dev); | 535 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 458 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 536 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 459 | struct sdhci_pxa *pxa = pltfm_host->priv; | 537 | struct sdhci_pxa *pxa = pltfm_host->priv; |
| 460 | unsigned long flags; | 538 | int ret; |
| 461 | 539 | ||
| 462 | spin_lock_irqsave(&host->lock, flags); | 540 | ret = sdhci_runtime_suspend_host(host); |
| 463 | host->runtime_suspended = true; | 541 | if (ret) |
| 464 | spin_unlock_irqrestore(&host->lock, flags); | 542 | return ret; |
| 465 | 543 | ||
| 466 | clk_disable_unprepare(pxa->clk_io); | 544 | clk_disable_unprepare(pxa->clk_io); |
| 467 | if (!IS_ERR(pxa->clk_core)) | 545 | if (!IS_ERR(pxa->clk_core)) |
| @@ -475,17 +553,12 @@ static int sdhci_pxav3_runtime_resume(struct device *dev) | |||
| 475 | struct sdhci_host *host = dev_get_drvdata(dev); | 553 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 476 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 554 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 477 | struct sdhci_pxa *pxa = pltfm_host->priv; | 555 | struct sdhci_pxa *pxa = pltfm_host->priv; |
| 478 | unsigned long flags; | ||
| 479 | 556 | ||
| 480 | clk_prepare_enable(pxa->clk_io); | 557 | clk_prepare_enable(pxa->clk_io); |
| 481 | if (!IS_ERR(pxa->clk_core)) | 558 | if (!IS_ERR(pxa->clk_core)) |
| 482 | clk_prepare_enable(pxa->clk_core); | 559 | clk_prepare_enable(pxa->clk_core); |
| 483 | 560 | ||
| 484 | spin_lock_irqsave(&host->lock, flags); | 561 | return sdhci_runtime_resume_host(host); |
| 485 | host->runtime_suspended = false; | ||
| 486 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 487 | |||
| 488 | return 0; | ||
| 489 | } | 562 | } |
| 490 | #endif | 563 | #endif |
| 491 | 564 | ||
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index c45b8932d843..c6d2dd7317c1 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #include <linux/spinlock.h> | ||
| 15 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| 16 | #include <linux/dma-mapping.h> | 17 | #include <linux/dma-mapping.h> |
| 17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
| @@ -312,7 +313,14 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 312 | 313 | ||
| 313 | sdhci_s3c_set_clock(host, clock); | 314 | sdhci_s3c_set_clock(host, clock); |
| 314 | 315 | ||
| 316 | /* Reset SD Clock Enable */ | ||
| 317 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | ||
| 318 | clk &= ~SDHCI_CLOCK_CARD_EN; | ||
| 319 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | ||
| 320 | |||
| 321 | spin_unlock_irq(&host->lock); | ||
| 315 | ret = clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock); | 322 | ret = clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock); |
| 323 | spin_lock_irq(&host->lock); | ||
| 316 | if (ret != 0) { | 324 | if (ret != 0) { |
| 317 | dev_err(dev, "%s: failed to set clock rate %uHz\n", | 325 | dev_err(dev, "%s: failed to set clock rate %uHz\n", |
| 318 | mmc_hostname(host->mmc), clock); | 326 | mmc_hostname(host->mmc), clock); |
| @@ -607,7 +615,9 @@ static int sdhci_s3c_probe(struct platform_device *pdev) | |||
| 607 | pm_runtime_use_autosuspend(&pdev->dev); | 615 | pm_runtime_use_autosuspend(&pdev->dev); |
| 608 | pm_suspend_ignore_children(&pdev->dev, 1); | 616 | pm_suspend_ignore_children(&pdev->dev, 1); |
| 609 | 617 | ||
| 610 | mmc_of_parse(host->mmc); | 618 | ret = mmc_of_parse(host->mmc); |
| 619 | if (ret) | ||
| 620 | goto err_req_regs; | ||
| 611 | 621 | ||
| 612 | ret = sdhci_add_host(host); | 622 | ret = sdhci_add_host(host); |
| 613 | if (ret) { | 623 | if (ret) { |
diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c index dd29d47c07aa..f6f82ec3618d 100644 --- a/drivers/mmc/host/sdhci-sirf.c +++ b/drivers/mmc/host/sdhci-sirf.c | |||
| @@ -15,7 +15,9 @@ | |||
| 15 | #include <linux/mmc/slot-gpio.h> | 15 | #include <linux/mmc/slot-gpio.h> |
| 16 | #include "sdhci-pltfm.h" | 16 | #include "sdhci-pltfm.h" |
| 17 | 17 | ||
| 18 | #define SDHCI_CLK_DELAY_SETTING 0x4C | ||
| 18 | #define SDHCI_SIRF_8BITBUS BIT(3) | 19 | #define SDHCI_SIRF_8BITBUS BIT(3) |
| 20 | #define SIRF_TUNING_COUNT 128 | ||
| 19 | 21 | ||
| 20 | struct sdhci_sirf_priv { | 22 | struct sdhci_sirf_priv { |
| 21 | struct clk *clk; | 23 | struct clk *clk; |
| @@ -49,7 +51,76 @@ static void sdhci_sirf_set_bus_width(struct sdhci_host *host, int width) | |||
| 49 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); | 51 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); |
| 50 | } | 52 | } |
| 51 | 53 | ||
| 54 | static int sdhci_sirf_execute_tuning(struct sdhci_host *host, u32 opcode) | ||
| 55 | { | ||
| 56 | int tuning_seq_cnt = 3; | ||
| 57 | u8 phase, tuned_phases[SIRF_TUNING_COUNT]; | ||
| 58 | u8 tuned_phase_cnt = 0; | ||
| 59 | int rc, longest_range = 0; | ||
| 60 | int start = -1, end = 0, tuning_value = -1, range = 0; | ||
| 61 | u16 clock_setting; | ||
| 62 | struct mmc_host *mmc = host->mmc; | ||
| 63 | |||
| 64 | clock_setting = sdhci_readw(host, SDHCI_CLK_DELAY_SETTING); | ||
| 65 | clock_setting &= ~0x3fff; | ||
| 66 | |||
| 67 | retry: | ||
| 68 | phase = 0; | ||
| 69 | do { | ||
| 70 | sdhci_writel(host, | ||
| 71 | clock_setting | phase | (phase << 7) | (phase << 16), | ||
| 72 | SDHCI_CLK_DELAY_SETTING); | ||
| 73 | |||
| 74 | if (!mmc_send_tuning(mmc)) { | ||
| 75 | /* Tuning is successful at this tuning point */ | ||
| 76 | tuned_phases[tuned_phase_cnt++] = phase; | ||
| 77 | dev_dbg(mmc_dev(mmc), "%s: Found good phase = %d\n", | ||
| 78 | mmc_hostname(mmc), phase); | ||
| 79 | if (start == -1) | ||
| 80 | start = phase; | ||
| 81 | end = phase; | ||
| 82 | range++; | ||
| 83 | if (phase == (SIRF_TUNING_COUNT - 1) | ||
| 84 | && range > longest_range) | ||
| 85 | tuning_value = (start + end) / 2; | ||
| 86 | } else { | ||
| 87 | dev_dbg(mmc_dev(mmc), "%s: Found bad phase = %d\n", | ||
| 88 | mmc_hostname(mmc), phase); | ||
| 89 | if (range > longest_range) { | ||
| 90 | tuning_value = (start + end) / 2; | ||
| 91 | longest_range = range; | ||
| 92 | } | ||
| 93 | start = -1; | ||
| 94 | end = range = 0; | ||
| 95 | } | ||
| 96 | } while (++phase < ARRAY_SIZE(tuned_phases)); | ||
| 97 | |||
| 98 | if (tuned_phase_cnt && tuning_value > 0) { | ||
| 99 | /* | ||
| 100 | * Finally set the selected phase in delay | ||
| 101 | * line hw block. | ||
| 102 | */ | ||
| 103 | phase = tuning_value; | ||
| 104 | sdhci_writel(host, | ||
| 105 | clock_setting | phase | (phase << 7) | (phase << 16), | ||
| 106 | SDHCI_CLK_DELAY_SETTING); | ||
| 107 | |||
| 108 | dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n", | ||
| 109 | mmc_hostname(mmc), phase); | ||
| 110 | } else { | ||
| 111 | if (--tuning_seq_cnt) | ||
| 112 | goto retry; | ||
| 113 | /* Tuning failed */ | ||
| 114 | dev_dbg(mmc_dev(mmc), "%s: No tuning point found\n", | ||
| 115 | mmc_hostname(mmc)); | ||
| 116 | rc = -EIO; | ||
| 117 | } | ||
| 118 | |||
| 119 | return rc; | ||
| 120 | } | ||
| 121 | |||
| 52 | static struct sdhci_ops sdhci_sirf_ops = { | 122 | static struct sdhci_ops sdhci_sirf_ops = { |
| 123 | .platform_execute_tuning = sdhci_sirf_execute_tuning, | ||
| 53 | .set_clock = sdhci_set_clock, | 124 | .set_clock = sdhci_set_clock, |
| 54 | .get_max_clock = sdhci_sirf_get_max_clk, | 125 | .get_max_clock = sdhci_sirf_get_max_clk, |
| 55 | .set_bus_width = sdhci_sirf_set_bus_width, | 126 | .set_bus_width = sdhci_sirf_set_bus_width, |
| @@ -138,9 +209,6 @@ static int sdhci_sirf_remove(struct platform_device *pdev) | |||
| 138 | 209 | ||
| 139 | sdhci_pltfm_unregister(pdev); | 210 | sdhci_pltfm_unregister(pdev); |
| 140 | 211 | ||
| 141 | if (gpio_is_valid(priv->gpio_cd)) | ||
| 142 | mmc_gpio_free_cd(host->mmc); | ||
| 143 | |||
| 144 | clk_disable_unprepare(priv->clk); | 212 | clk_disable_unprepare(priv->clk); |
| 145 | return 0; | 213 | return 0; |
| 146 | } | 214 | } |
diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 328f348c7243..882b07e9667e 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c | |||
| @@ -78,10 +78,9 @@ static int sdhci_st_probe(struct platform_device *pdev) | |||
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | ret = mmc_of_parse(host->mmc); | 80 | ret = mmc_of_parse(host->mmc); |
| 81 | |||
| 82 | if (ret) { | 81 | if (ret) { |
| 83 | dev_err(&pdev->dev, "Failed mmc_of_parse\n"); | 82 | dev_err(&pdev->dev, "Failed mmc_of_parse\n"); |
| 84 | return ret; | 83 | goto err_of; |
| 85 | } | 84 | } |
| 86 | 85 | ||
| 87 | clk_prepare_enable(clk); | 86 | clk_prepare_enable(clk); |
| @@ -108,6 +107,7 @@ static int sdhci_st_probe(struct platform_device *pdev) | |||
| 108 | 107 | ||
| 109 | err_out: | 108 | err_out: |
| 110 | clk_disable_unprepare(clk); | 109 | clk_disable_unprepare(clk); |
| 110 | err_of: | ||
| 111 | sdhci_pltfm_free(pdev); | 111 | sdhci_pltfm_free(pdev); |
| 112 | 112 | ||
| 113 | return ret; | 113 | return ret; |
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 59797106af93..f3778d58d1cd 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #define NVQUIRK_DISABLE_SDR50 BIT(3) | 41 | #define NVQUIRK_DISABLE_SDR50 BIT(3) |
| 42 | #define NVQUIRK_DISABLE_SDR104 BIT(4) | 42 | #define NVQUIRK_DISABLE_SDR104 BIT(4) |
| 43 | #define NVQUIRK_DISABLE_DDR50 BIT(5) | 43 | #define NVQUIRK_DISABLE_DDR50 BIT(5) |
| 44 | #define NVQUIRK_SHADOW_XFER_MODE_REG BIT(6) | ||
| 44 | 45 | ||
| 45 | struct sdhci_tegra_soc_data { | 46 | struct sdhci_tegra_soc_data { |
| 46 | const struct sdhci_pltfm_data *pdata; | 47 | const struct sdhci_pltfm_data *pdata; |
| @@ -67,6 +68,31 @@ static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) | |||
| 67 | return readw(host->ioaddr + reg); | 68 | return readw(host->ioaddr + reg); |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 71 | static void tegra_sdhci_writew(struct sdhci_host *host, u16 val, int reg) | ||
| 72 | { | ||
| 73 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 74 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | ||
| 75 | const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; | ||
| 76 | |||
| 77 | if (soc_data->nvquirks & NVQUIRK_SHADOW_XFER_MODE_REG) { | ||
| 78 | switch (reg) { | ||
| 79 | case SDHCI_TRANSFER_MODE: | ||
| 80 | /* | ||
| 81 | * Postpone this write, we must do it together with a | ||
| 82 | * command write that is down below. | ||
| 83 | */ | ||
| 84 | pltfm_host->xfer_mode_shadow = val; | ||
| 85 | return; | ||
| 86 | case SDHCI_COMMAND: | ||
| 87 | writel((val << 16) | pltfm_host->xfer_mode_shadow, | ||
| 88 | host->ioaddr + SDHCI_TRANSFER_MODE); | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | writew(val, host->ioaddr + reg); | ||
| 94 | } | ||
| 95 | |||
| 70 | static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) | 96 | static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) |
| 71 | { | 97 | { |
| 72 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 98 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| @@ -147,6 +173,7 @@ static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width) | |||
| 147 | static const struct sdhci_ops tegra_sdhci_ops = { | 173 | static const struct sdhci_ops tegra_sdhci_ops = { |
| 148 | .get_ro = tegra_sdhci_get_ro, | 174 | .get_ro = tegra_sdhci_get_ro, |
| 149 | .read_w = tegra_sdhci_readw, | 175 | .read_w = tegra_sdhci_readw, |
| 176 | .write_w = tegra_sdhci_writew, | ||
| 150 | .write_l = tegra_sdhci_writel, | 177 | .write_l = tegra_sdhci_writel, |
| 151 | .set_clock = sdhci_set_clock, | 178 | .set_clock = sdhci_set_clock, |
| 152 | .set_bus_width = tegra_sdhci_set_bus_width, | 179 | .set_bus_width = tegra_sdhci_set_bus_width, |
| @@ -201,7 +228,8 @@ static struct sdhci_tegra_soc_data soc_data_tegra114 = { | |||
| 201 | .pdata = &sdhci_tegra114_pdata, | 228 | .pdata = &sdhci_tegra114_pdata, |
| 202 | .nvquirks = NVQUIRK_DISABLE_SDR50 | | 229 | .nvquirks = NVQUIRK_DISABLE_SDR50 | |
| 203 | NVQUIRK_DISABLE_DDR50 | | 230 | NVQUIRK_DISABLE_DDR50 | |
| 204 | NVQUIRK_DISABLE_SDR104, | 231 | NVQUIRK_DISABLE_SDR104 | |
| 232 | NVQUIRK_SHADOW_XFER_MODE_REG, | ||
| 205 | }; | 233 | }; |
| 206 | 234 | ||
| 207 | static const struct of_device_id sdhci_tegra_dt_match[] = { | 235 | static const struct of_device_id sdhci_tegra_dt_match[] = { |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f1a488ee432f..0ad412a4876f 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -53,6 +53,9 @@ static void sdhci_finish_command(struct sdhci_host *); | |||
| 53 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); | 53 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); |
| 54 | static void sdhci_tuning_timer(unsigned long data); | 54 | static void sdhci_tuning_timer(unsigned long data); |
| 55 | static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); | 55 | static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); |
| 56 | static int sdhci_pre_dma_transfer(struct sdhci_host *host, | ||
| 57 | struct mmc_data *data, | ||
| 58 | struct sdhci_host_next *next); | ||
| 56 | 59 | ||
| 57 | #ifdef CONFIG_PM | 60 | #ifdef CONFIG_PM |
| 58 | static int sdhci_runtime_pm_get(struct sdhci_host *host); | 61 | static int sdhci_runtime_pm_get(struct sdhci_host *host); |
| @@ -505,9 +508,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, | |||
| 505 | goto fail; | 508 | goto fail; |
| 506 | BUG_ON(host->align_addr & host->align_mask); | 509 | BUG_ON(host->align_addr & host->align_mask); |
| 507 | 510 | ||
| 508 | host->sg_count = dma_map_sg(mmc_dev(host->mmc), | 511 | host->sg_count = sdhci_pre_dma_transfer(host, data, NULL); |
| 509 | data->sg, data->sg_len, direction); | 512 | if (host->sg_count < 0) |
| 510 | if (host->sg_count == 0) | ||
| 511 | goto unmap_align; | 513 | goto unmap_align; |
| 512 | 514 | ||
| 513 | desc = host->adma_table; | 515 | desc = host->adma_table; |
| @@ -531,8 +533,6 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, | |||
| 531 | if (offset) { | 533 | if (offset) { |
| 532 | if (data->flags & MMC_DATA_WRITE) { | 534 | if (data->flags & MMC_DATA_WRITE) { |
| 533 | buffer = sdhci_kmap_atomic(sg, &flags); | 535 | buffer = sdhci_kmap_atomic(sg, &flags); |
| 534 | WARN_ON(((long)buffer & (PAGE_SIZE - 1)) > | ||
| 535 | (PAGE_SIZE - offset)); | ||
| 536 | memcpy(align, buffer, offset); | 536 | memcpy(align, buffer, offset); |
| 537 | sdhci_kunmap_atomic(buffer, &flags); | 537 | sdhci_kunmap_atomic(buffer, &flags); |
| 538 | } | 538 | } |
| @@ -639,8 +639,6 @@ static void sdhci_adma_table_post(struct sdhci_host *host, | |||
| 639 | (sg_dma_address(sg) & host->align_mask); | 639 | (sg_dma_address(sg) & host->align_mask); |
| 640 | 640 | ||
| 641 | buffer = sdhci_kmap_atomic(sg, &flags); | 641 | buffer = sdhci_kmap_atomic(sg, &flags); |
| 642 | WARN_ON(((long)buffer & (PAGE_SIZE - 1)) > | ||
| 643 | (PAGE_SIZE - size)); | ||
| 644 | memcpy(buffer, align, size); | 642 | memcpy(buffer, align, size); |
| 645 | sdhci_kunmap_atomic(buffer, &flags); | 643 | sdhci_kunmap_atomic(buffer, &flags); |
| 646 | 644 | ||
| @@ -649,8 +647,9 @@ static void sdhci_adma_table_post(struct sdhci_host *host, | |||
| 649 | } | 647 | } |
| 650 | } | 648 | } |
| 651 | 649 | ||
| 652 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, | 650 | if (!data->host_cookie) |
| 653 | data->sg_len, direction); | 651 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, |
| 652 | data->sg_len, direction); | ||
| 654 | } | 653 | } |
| 655 | 654 | ||
| 656 | static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) | 655 | static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) |
| @@ -846,11 +845,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) | |||
| 846 | } else { | 845 | } else { |
| 847 | int sg_cnt; | 846 | int sg_cnt; |
| 848 | 847 | ||
| 849 | sg_cnt = dma_map_sg(mmc_dev(host->mmc), | 848 | sg_cnt = sdhci_pre_dma_transfer(host, data, NULL); |
| 850 | data->sg, data->sg_len, | ||
| 851 | (data->flags & MMC_DATA_READ) ? | ||
| 852 | DMA_FROM_DEVICE : | ||
| 853 | DMA_TO_DEVICE); | ||
| 854 | if (sg_cnt == 0) { | 849 | if (sg_cnt == 0) { |
| 855 | /* | 850 | /* |
| 856 | * This only happens when someone fed | 851 | * This only happens when someone fed |
| @@ -909,7 +904,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) | |||
| 909 | static void sdhci_set_transfer_mode(struct sdhci_host *host, | 904 | static void sdhci_set_transfer_mode(struct sdhci_host *host, |
| 910 | struct mmc_command *cmd) | 905 | struct mmc_command *cmd) |
| 911 | { | 906 | { |
| 912 | u16 mode; | 907 | u16 mode = 0; |
| 913 | struct mmc_data *data = cmd->data; | 908 | struct mmc_data *data = cmd->data; |
| 914 | 909 | ||
| 915 | if (data == NULL) { | 910 | if (data == NULL) { |
| @@ -927,9 +922,11 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, | |||
| 927 | 922 | ||
| 928 | WARN_ON(!host->data); | 923 | WARN_ON(!host->data); |
| 929 | 924 | ||
| 930 | mode = SDHCI_TRNS_BLK_CNT_EN; | 925 | if (!(host->quirks2 & SDHCI_QUIRK2_SUPPORT_SINGLE)) |
| 926 | mode = SDHCI_TRNS_BLK_CNT_EN; | ||
| 927 | |||
| 931 | if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { | 928 | if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { |
| 932 | mode |= SDHCI_TRNS_MULTI; | 929 | mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI; |
| 933 | /* | 930 | /* |
| 934 | * If we are sending CMD23, CMD12 never gets sent | 931 | * If we are sending CMD23, CMD12 never gets sent |
| 935 | * on successful completion (so no Auto-CMD12). | 932 | * on successful completion (so no Auto-CMD12). |
| @@ -963,8 +960,10 @@ static void sdhci_finish_data(struct sdhci_host *host) | |||
| 963 | if (host->flags & SDHCI_USE_ADMA) | 960 | if (host->flags & SDHCI_USE_ADMA) |
| 964 | sdhci_adma_table_post(host, data); | 961 | sdhci_adma_table_post(host, data); |
| 965 | else { | 962 | else { |
| 966 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, | 963 | if (!data->host_cookie) |
| 967 | data->sg_len, (data->flags & MMC_DATA_READ) ? | 964 | dma_unmap_sg(mmc_dev(host->mmc), |
| 965 | data->sg, data->sg_len, | ||
| 966 | (data->flags & MMC_DATA_READ) ? | ||
| 968 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | 967 | DMA_FROM_DEVICE : DMA_TO_DEVICE); |
| 969 | } | 968 | } |
| 970 | } | 969 | } |
| @@ -1630,7 +1629,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) | |||
| 1630 | * signalling timeout and CRC errors even on CMD0. Resetting | 1629 | * signalling timeout and CRC errors even on CMD0. Resetting |
| 1631 | * it on each ios seems to solve the problem. | 1630 | * it on each ios seems to solve the problem. |
| 1632 | */ | 1631 | */ |
| 1633 | if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) | 1632 | if (host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) |
| 1634 | sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); | 1633 | sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); |
| 1635 | 1634 | ||
| 1636 | mmiowb(); | 1635 | mmiowb(); |
| @@ -1832,6 +1831,10 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, | |||
| 1832 | ctrl |= SDHCI_CTRL_VDD_180; | 1831 | ctrl |= SDHCI_CTRL_VDD_180; |
| 1833 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | 1832 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
| 1834 | 1833 | ||
| 1834 | /* Some controller need to do more when switching */ | ||
| 1835 | if (host->ops->voltage_switch) | ||
| 1836 | host->ops->voltage_switch(host); | ||
| 1837 | |||
| 1835 | /* 1.8V regulator output should be stable within 5 ms */ | 1838 | /* 1.8V regulator output should be stable within 5 ms */ |
| 1836 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1839 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
| 1837 | if (ctrl & SDHCI_CTRL_VDD_180) | 1840 | if (ctrl & SDHCI_CTRL_VDD_180) |
| @@ -1960,6 +1963,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 1960 | 1963 | ||
| 1961 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1964 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
| 1962 | ctrl |= SDHCI_CTRL_EXEC_TUNING; | 1965 | ctrl |= SDHCI_CTRL_EXEC_TUNING; |
| 1966 | if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND) | ||
| 1967 | ctrl |= SDHCI_CTRL_TUNED_CLK; | ||
| 1963 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | 1968 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
| 1964 | 1969 | ||
| 1965 | /* | 1970 | /* |
| @@ -2129,6 +2134,77 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) | |||
| 2129 | } | 2134 | } |
| 2130 | } | 2135 | } |
| 2131 | 2136 | ||
| 2137 | static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, | ||
| 2138 | int err) | ||
| 2139 | { | ||
| 2140 | struct sdhci_host *host = mmc_priv(mmc); | ||
| 2141 | struct mmc_data *data = mrq->data; | ||
| 2142 | |||
| 2143 | if (host->flags & SDHCI_REQ_USE_DMA) { | ||
| 2144 | if (data->host_cookie) | ||
| 2145 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, | ||
| 2146 | data->flags & MMC_DATA_WRITE ? | ||
| 2147 | DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
| 2148 | mrq->data->host_cookie = 0; | ||
| 2149 | } | ||
| 2150 | } | ||
| 2151 | |||
| 2152 | static int sdhci_pre_dma_transfer(struct sdhci_host *host, | ||
| 2153 | struct mmc_data *data, | ||
| 2154 | struct sdhci_host_next *next) | ||
| 2155 | { | ||
| 2156 | int sg_count; | ||
| 2157 | |||
| 2158 | if (!next && data->host_cookie && | ||
| 2159 | data->host_cookie != host->next_data.cookie) { | ||
| 2160 | pr_debug(DRIVER_NAME "[%s] invalid cookie: %d, next-cookie %d\n", | ||
| 2161 | __func__, data->host_cookie, host->next_data.cookie); | ||
| 2162 | data->host_cookie = 0; | ||
| 2163 | } | ||
| 2164 | |||
| 2165 | /* Check if next job is already prepared */ | ||
| 2166 | if (next || | ||
| 2167 | (!next && data->host_cookie != host->next_data.cookie)) { | ||
| 2168 | sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, | ||
| 2169 | data->sg_len, | ||
| 2170 | data->flags & MMC_DATA_WRITE ? | ||
| 2171 | DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
| 2172 | |||
| 2173 | } else { | ||
| 2174 | sg_count = host->next_data.sg_count; | ||
| 2175 | host->next_data.sg_count = 0; | ||
| 2176 | } | ||
| 2177 | |||
| 2178 | |||
| 2179 | if (sg_count == 0) | ||
| 2180 | return -EINVAL; | ||
| 2181 | |||
| 2182 | if (next) { | ||
| 2183 | next->sg_count = sg_count; | ||
| 2184 | data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie; | ||
| 2185 | } else | ||
| 2186 | host->sg_count = sg_count; | ||
| 2187 | |||
| 2188 | return sg_count; | ||
| 2189 | } | ||
| 2190 | |||
| 2191 | static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, | ||
| 2192 | bool is_first_req) | ||
| 2193 | { | ||
| 2194 | struct sdhci_host *host = mmc_priv(mmc); | ||
| 2195 | |||
| 2196 | if (mrq->data->host_cookie) { | ||
| 2197 | mrq->data->host_cookie = 0; | ||
| 2198 | return; | ||
| 2199 | } | ||
| 2200 | |||
| 2201 | if (host->flags & SDHCI_REQ_USE_DMA) | ||
| 2202 | if (sdhci_pre_dma_transfer(host, | ||
| 2203 | mrq->data, | ||
| 2204 | &host->next_data) < 0) | ||
| 2205 | mrq->data->host_cookie = 0; | ||
| 2206 | } | ||
| 2207 | |||
| 2132 | static void sdhci_card_event(struct mmc_host *mmc) | 2208 | static void sdhci_card_event(struct mmc_host *mmc) |
| 2133 | { | 2209 | { |
| 2134 | struct sdhci_host *host = mmc_priv(mmc); | 2210 | struct sdhci_host *host = mmc_priv(mmc); |
| @@ -2162,6 +2238,8 @@ static void sdhci_card_event(struct mmc_host *mmc) | |||
| 2162 | 2238 | ||
| 2163 | static const struct mmc_host_ops sdhci_ops = { | 2239 | static const struct mmc_host_ops sdhci_ops = { |
| 2164 | .request = sdhci_request, | 2240 | .request = sdhci_request, |
| 2241 | .post_req = sdhci_post_req, | ||
| 2242 | .pre_req = sdhci_pre_req, | ||
| 2165 | .set_ios = sdhci_set_ios, | 2243 | .set_ios = sdhci_set_ios, |
| 2166 | .get_cd = sdhci_get_cd, | 2244 | .get_cd = sdhci_get_cd, |
| 2167 | .get_ro = sdhci_get_ro, | 2245 | .get_ro = sdhci_get_ro, |
| @@ -2793,9 +2871,9 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) | |||
| 2793 | /* Force clock and power re-program */ | 2871 | /* Force clock and power re-program */ |
| 2794 | host->pwr = 0; | 2872 | host->pwr = 0; |
| 2795 | host->clock = 0; | 2873 | host->clock = 0; |
| 2874 | sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios); | ||
| 2796 | sdhci_do_set_ios(host, &host->mmc->ios); | 2875 | sdhci_do_set_ios(host, &host->mmc->ios); |
| 2797 | 2876 | ||
| 2798 | sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios); | ||
| 2799 | if ((host_flags & SDHCI_PV_ENABLED) && | 2877 | if ((host_flags & SDHCI_PV_ENABLED) && |
| 2800 | !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { | 2878 | !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { |
| 2801 | spin_lock_irqsave(&host->lock, flags); | 2879 | spin_lock_irqsave(&host->lock, flags); |
| @@ -3019,6 +3097,7 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 3019 | host->max_clk = host->ops->get_max_clock(host); | 3097 | host->max_clk = host->ops->get_max_clock(host); |
| 3020 | } | 3098 | } |
| 3021 | 3099 | ||
| 3100 | host->next_data.cookie = 1; | ||
| 3022 | /* | 3101 | /* |
| 3023 | * In case of Host Controller v3.00, find out whether clock | 3102 | * In case of Host Controller v3.00, find out whether clock |
| 3024 | * multiplier is supported. | 3103 | * multiplier is supported. |
| @@ -3338,9 +3417,9 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 3338 | 3417 | ||
| 3339 | setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); | 3418 | setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); |
| 3340 | 3419 | ||
| 3341 | if (host->version >= SDHCI_SPEC_300) { | 3420 | init_waitqueue_head(&host->buf_ready_int); |
| 3342 | init_waitqueue_head(&host->buf_ready_int); | ||
| 3343 | 3421 | ||
| 3422 | if (host->version >= SDHCI_SPEC_300) { | ||
| 3344 | /* Initialize re-tuning timer */ | 3423 | /* Initialize re-tuning timer */ |
| 3345 | init_timer(&host->tuning_timer); | 3424 | init_timer(&host->tuning_timer); |
| 3346 | host->tuning_timer.data = (unsigned long)host; | 3425 | host->tuning_timer.data = (unsigned long)host; |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 41a2c34299ed..0315e1844330 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
| @@ -339,6 +339,7 @@ struct sdhci_ops { | |||
| 339 | void (*adma_workaround)(struct sdhci_host *host, u32 intmask); | 339 | void (*adma_workaround)(struct sdhci_host *host, u32 intmask); |
| 340 | void (*platform_init)(struct sdhci_host *host); | 340 | void (*platform_init)(struct sdhci_host *host); |
| 341 | void (*card_event)(struct sdhci_host *host); | 341 | void (*card_event)(struct sdhci_host *host); |
| 342 | void (*voltage_switch)(struct sdhci_host *host); | ||
| 342 | }; | 343 | }; |
| 343 | 344 | ||
| 344 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS | 345 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS |
diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c new file mode 100644 index 000000000000..2fe8b91481b3 --- /dev/null +++ b/drivers/mmc/host/sdhci_f_sdh30.c | |||
| @@ -0,0 +1,237 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/mmc/host/sdhci_f_sdh30.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 - 2015 Fujitsu Semiconductor, Ltd | ||
| 5 | * Vincent Yang <vincent.yang@tw.fujitsu.com> | ||
| 6 | * Copyright (C) 2015 Linaro Ltd Andy Green <andy.green@linaro.org> | ||
| 7 | * | ||
| 8 | * This program is free software: you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation, version 2 of the License. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/clk.h> | ||
| 17 | |||
| 18 | #include "sdhci-pltfm.h" | ||
| 19 | |||
| 20 | /* F_SDH30 extended Controller registers */ | ||
| 21 | #define F_SDH30_AHB_CONFIG 0x100 | ||
| 22 | #define F_SDH30_AHB_BIGED 0x00000040 | ||
| 23 | #define F_SDH30_BUSLOCK_DMA 0x00000020 | ||
| 24 | #define F_SDH30_BUSLOCK_EN 0x00000010 | ||
| 25 | #define F_SDH30_SIN 0x00000008 | ||
| 26 | #define F_SDH30_AHB_INCR_16 0x00000004 | ||
| 27 | #define F_SDH30_AHB_INCR_8 0x00000002 | ||
| 28 | #define F_SDH30_AHB_INCR_4 0x00000001 | ||
| 29 | |||
| 30 | #define F_SDH30_TUNING_SETTING 0x108 | ||
| 31 | #define F_SDH30_CMD_CHK_DIS 0x00010000 | ||
| 32 | |||
| 33 | #define F_SDH30_IO_CONTROL2 0x114 | ||
| 34 | #define F_SDH30_CRES_O_DN 0x00080000 | ||
| 35 | #define F_SDH30_MSEL_O_1_8 0x00040000 | ||
| 36 | |||
| 37 | #define F_SDH30_ESD_CONTROL 0x124 | ||
| 38 | #define F_SDH30_EMMC_RST 0x00000002 | ||
| 39 | #define F_SDH30_EMMC_HS200 0x01000000 | ||
| 40 | |||
| 41 | #define F_SDH30_CMD_DAT_DELAY 0x200 | ||
| 42 | |||
| 43 | #define F_SDH30_MIN_CLOCK 400000 | ||
| 44 | |||
| 45 | struct f_sdhost_priv { | ||
| 46 | struct clk *clk_iface; | ||
| 47 | struct clk *clk; | ||
| 48 | u32 vendor_hs200; | ||
| 49 | struct device *dev; | ||
| 50 | }; | ||
| 51 | |||
| 52 | void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host) | ||
| 53 | { | ||
| 54 | struct f_sdhost_priv *priv = sdhci_priv(host); | ||
| 55 | u32 ctrl = 0; | ||
| 56 | |||
| 57 | usleep_range(2500, 3000); | ||
| 58 | ctrl = sdhci_readl(host, F_SDH30_IO_CONTROL2); | ||
| 59 | ctrl |= F_SDH30_CRES_O_DN; | ||
| 60 | sdhci_writel(host, ctrl, F_SDH30_IO_CONTROL2); | ||
| 61 | ctrl |= F_SDH30_MSEL_O_1_8; | ||
| 62 | sdhci_writel(host, ctrl, F_SDH30_IO_CONTROL2); | ||
| 63 | |||
| 64 | ctrl &= ~F_SDH30_CRES_O_DN; | ||
| 65 | sdhci_writel(host, ctrl, F_SDH30_IO_CONTROL2); | ||
| 66 | usleep_range(2500, 3000); | ||
| 67 | |||
| 68 | if (priv->vendor_hs200) { | ||
| 69 | dev_info(priv->dev, "%s: setting hs200\n", __func__); | ||
| 70 | ctrl = sdhci_readl(host, F_SDH30_ESD_CONTROL); | ||
| 71 | ctrl |= priv->vendor_hs200; | ||
| 72 | sdhci_writel(host, ctrl, F_SDH30_ESD_CONTROL); | ||
| 73 | } | ||
| 74 | |||
| 75 | ctrl = sdhci_readl(host, F_SDH30_TUNING_SETTING); | ||
| 76 | ctrl |= F_SDH30_CMD_CHK_DIS; | ||
| 77 | sdhci_writel(host, ctrl, F_SDH30_TUNING_SETTING); | ||
| 78 | } | ||
| 79 | |||
| 80 | unsigned int sdhci_f_sdh30_get_min_clock(struct sdhci_host *host) | ||
| 81 | { | ||
| 82 | return F_SDH30_MIN_CLOCK; | ||
| 83 | } | ||
| 84 | |||
| 85 | void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask) | ||
| 86 | { | ||
| 87 | if (sdhci_readw(host, SDHCI_CLOCK_CONTROL) == 0) | ||
| 88 | sdhci_writew(host, 0xBC01, SDHCI_CLOCK_CONTROL); | ||
| 89 | |||
| 90 | sdhci_reset(host, mask); | ||
| 91 | } | ||
| 92 | |||
| 93 | static const struct sdhci_ops sdhci_f_sdh30_ops = { | ||
| 94 | .voltage_switch = sdhci_f_sdh30_soft_voltage_switch, | ||
| 95 | .get_min_clock = sdhci_f_sdh30_get_min_clock, | ||
| 96 | .reset = sdhci_f_sdh30_reset, | ||
| 97 | .set_clock = sdhci_set_clock, | ||
| 98 | .set_bus_width = sdhci_set_bus_width, | ||
| 99 | .set_uhs_signaling = sdhci_set_uhs_signaling, | ||
| 100 | }; | ||
| 101 | |||
| 102 | static int sdhci_f_sdh30_probe(struct platform_device *pdev) | ||
| 103 | { | ||
| 104 | struct sdhci_host *host; | ||
| 105 | struct device *dev = &pdev->dev; | ||
| 106 | struct resource *res; | ||
| 107 | int irq, ctrl = 0, ret = 0; | ||
| 108 | struct f_sdhost_priv *priv; | ||
| 109 | u32 reg = 0; | ||
| 110 | |||
| 111 | irq = platform_get_irq(pdev, 0); | ||
| 112 | if (irq < 0) { | ||
| 113 | dev_err(dev, "%s: no irq specified\n", __func__); | ||
| 114 | return irq; | ||
| 115 | } | ||
| 116 | |||
| 117 | host = sdhci_alloc_host(dev, sizeof(struct sdhci_host) + | ||
| 118 | sizeof(struct f_sdhost_priv)); | ||
| 119 | if (IS_ERR(host)) | ||
| 120 | return PTR_ERR(host); | ||
| 121 | |||
| 122 | priv = sdhci_priv(host); | ||
| 123 | priv->dev = dev; | ||
| 124 | |||
| 125 | host->quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | | ||
| 126 | SDHCI_QUIRK_INVERTED_WRITE_PROTECT; | ||
| 127 | host->quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE | | ||
| 128 | SDHCI_QUIRK2_TUNING_WORK_AROUND; | ||
| 129 | |||
| 130 | ret = mmc_of_parse(host->mmc); | ||
| 131 | if (ret) | ||
| 132 | goto err; | ||
| 133 | |||
| 134 | platform_set_drvdata(pdev, host); | ||
| 135 | |||
| 136 | sdhci_get_of_property(pdev); | ||
| 137 | host->hw_name = "f_sdh30"; | ||
| 138 | host->ops = &sdhci_f_sdh30_ops; | ||
| 139 | host->irq = irq; | ||
| 140 | |||
| 141 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 142 | host->ioaddr = devm_ioremap_resource(&pdev->dev, res); | ||
| 143 | if (IS_ERR(host->ioaddr)) { | ||
| 144 | ret = PTR_ERR(host->ioaddr); | ||
| 145 | goto err; | ||
| 146 | } | ||
| 147 | |||
| 148 | priv->clk_iface = devm_clk_get(&pdev->dev, "iface"); | ||
| 149 | if (IS_ERR(priv->clk_iface)) { | ||
| 150 | ret = PTR_ERR(priv->clk_iface); | ||
| 151 | goto err; | ||
| 152 | } | ||
| 153 | |||
| 154 | ret = clk_prepare_enable(priv->clk_iface); | ||
| 155 | if (ret) | ||
| 156 | goto err; | ||
| 157 | |||
| 158 | priv->clk = devm_clk_get(&pdev->dev, "core"); | ||
| 159 | if (IS_ERR(priv->clk)) { | ||
| 160 | ret = PTR_ERR(priv->clk); | ||
| 161 | goto err_clk; | ||
| 162 | } | ||
| 163 | |||
| 164 | ret = clk_prepare_enable(priv->clk); | ||
| 165 | if (ret) | ||
| 166 | goto err_clk; | ||
| 167 | |||
| 168 | /* init vendor specific regs */ | ||
| 169 | ctrl = sdhci_readw(host, F_SDH30_AHB_CONFIG); | ||
| 170 | ctrl |= F_SDH30_SIN | F_SDH30_AHB_INCR_16 | F_SDH30_AHB_INCR_8 | | ||
| 171 | F_SDH30_AHB_INCR_4; | ||
| 172 | ctrl &= ~(F_SDH30_AHB_BIGED | F_SDH30_BUSLOCK_EN); | ||
| 173 | sdhci_writew(host, ctrl, F_SDH30_AHB_CONFIG); | ||
| 174 | |||
| 175 | reg = sdhci_readl(host, F_SDH30_ESD_CONTROL); | ||
| 176 | sdhci_writel(host, reg & ~F_SDH30_EMMC_RST, F_SDH30_ESD_CONTROL); | ||
| 177 | msleep(20); | ||
| 178 | sdhci_writel(host, reg | F_SDH30_EMMC_RST, F_SDH30_ESD_CONTROL); | ||
| 179 | |||
| 180 | reg = sdhci_readl(host, SDHCI_CAPABILITIES); | ||
| 181 | if (reg & SDHCI_CAN_DO_8BIT) | ||
| 182 | priv->vendor_hs200 = F_SDH30_EMMC_HS200; | ||
| 183 | |||
| 184 | ret = sdhci_add_host(host); | ||
| 185 | if (ret) | ||
| 186 | goto err_add_host; | ||
| 187 | |||
| 188 | return 0; | ||
| 189 | |||
| 190 | err_add_host: | ||
| 191 | clk_disable_unprepare(priv->clk); | ||
| 192 | err_clk: | ||
| 193 | clk_disable_unprepare(priv->clk_iface); | ||
| 194 | err: | ||
| 195 | sdhci_free_host(host); | ||
| 196 | return ret; | ||
| 197 | } | ||
| 198 | |||
| 199 | static int sdhci_f_sdh30_remove(struct platform_device *pdev) | ||
| 200 | { | ||
| 201 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
| 202 | struct f_sdhost_priv *priv = sdhci_priv(host); | ||
| 203 | |||
| 204 | sdhci_remove_host(host, readl(host->ioaddr + SDHCI_INT_STATUS) == | ||
| 205 | 0xffffffff); | ||
| 206 | |||
| 207 | clk_disable_unprepare(priv->clk_iface); | ||
| 208 | clk_disable_unprepare(priv->clk); | ||
| 209 | |||
| 210 | sdhci_free_host(host); | ||
| 211 | platform_set_drvdata(pdev, NULL); | ||
| 212 | |||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 216 | static const struct of_device_id f_sdh30_dt_ids[] = { | ||
| 217 | { .compatible = "fujitsu,mb86s70-sdhci-3.0" }, | ||
| 218 | { /* sentinel */ } | ||
| 219 | }; | ||
| 220 | MODULE_DEVICE_TABLE(of, f_sdh30_dt_ids); | ||
| 221 | |||
| 222 | static struct platform_driver sdhci_f_sdh30_driver = { | ||
| 223 | .driver = { | ||
| 224 | .name = "f_sdh30", | ||
| 225 | .of_match_table = f_sdh30_dt_ids, | ||
| 226 | .pm = SDHCI_PLTFM_PMOPS, | ||
| 227 | }, | ||
| 228 | .probe = sdhci_f_sdh30_probe, | ||
| 229 | .remove = sdhci_f_sdh30_remove, | ||
| 230 | }; | ||
| 231 | |||
| 232 | module_platform_driver(sdhci_f_sdh30_driver); | ||
| 233 | |||
| 234 | MODULE_DESCRIPTION("F_SDH30 SD Card Controller driver"); | ||
| 235 | MODULE_LICENSE("GPL v2"); | ||
| 236 | MODULE_AUTHOR("FUJITSU SEMICONDUCTOR LTD."); | ||
| 237 | MODULE_ALIAS("platform:f_sdh30"); | ||
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index 00c8ebdf8ec7..6906a905cd54 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c | |||
| @@ -35,10 +35,13 @@ | |||
| 35 | 35 | ||
| 36 | #define EXT_ACC 0xe4 | 36 | #define EXT_ACC 0xe4 |
| 37 | 37 | ||
| 38 | #define host_to_priv(host) container_of((host)->pdata, struct sh_mobile_sdhi, mmc_data) | ||
| 39 | |||
| 38 | struct sh_mobile_sdhi_of_data { | 40 | struct sh_mobile_sdhi_of_data { |
| 39 | unsigned long tmio_flags; | 41 | unsigned long tmio_flags; |
| 40 | unsigned long capabilities; | 42 | unsigned long capabilities; |
| 41 | unsigned long capabilities2; | 43 | unsigned long capabilities2; |
| 44 | enum dma_slave_buswidth dma_buswidth; | ||
| 42 | dma_addr_t dma_rx_offset; | 45 | dma_addr_t dma_rx_offset; |
| 43 | }; | 46 | }; |
| 44 | 47 | ||
| @@ -58,6 +61,7 @@ static const struct sh_mobile_sdhi_of_data of_rcar_gen2_compatible = { | |||
| 58 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | | 61 | .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE | |
| 59 | TMIO_MMC_CLK_ACTUAL, | 62 | TMIO_MMC_CLK_ACTUAL, |
| 60 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, | 63 | .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, |
| 64 | .dma_buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES, | ||
| 61 | .dma_rx_offset = 0x2000, | 65 | .dma_rx_offset = 0x2000, |
| 62 | }; | 66 | }; |
| 63 | 67 | ||
| @@ -84,16 +88,43 @@ struct sh_mobile_sdhi { | |||
| 84 | struct tmio_mmc_dma dma_priv; | 88 | struct tmio_mmc_dma dma_priv; |
| 85 | }; | 89 | }; |
| 86 | 90 | ||
| 91 | static void sh_mobile_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width) | ||
| 92 | { | ||
| 93 | u32 val; | ||
| 94 | |||
| 95 | /* | ||
| 96 | * see also | ||
| 97 | * sh_mobile_sdhi_of_data :: dma_buswidth | ||
| 98 | */ | ||
| 99 | switch (sd_ctrl_read16(host, CTL_VERSION)) { | ||
| 100 | case 0x490C: | ||
| 101 | val = (width == 32) ? 0x0001 : 0x0000; | ||
| 102 | break; | ||
| 103 | case 0xCB0D: | ||
| 104 | val = (width == 32) ? 0x0000 : 0x0001; | ||
| 105 | break; | ||
| 106 | default: | ||
| 107 | /* nothing to do */ | ||
| 108 | return; | ||
| 109 | } | ||
| 110 | |||
| 111 | sd_ctrl_write16(host, EXT_ACC, val); | ||
| 112 | } | ||
| 113 | |||
| 87 | static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f) | 114 | static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f) |
| 88 | { | 115 | { |
| 89 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 116 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 90 | struct tmio_mmc_host *host = mmc_priv(mmc); | 117 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 91 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); | 118 | struct sh_mobile_sdhi *priv = host_to_priv(host); |
| 92 | int ret = clk_prepare_enable(priv->clk); | 119 | int ret = clk_prepare_enable(priv->clk); |
| 93 | if (ret < 0) | 120 | if (ret < 0) |
| 94 | return ret; | 121 | return ret; |
| 95 | 122 | ||
| 96 | *f = clk_get_rate(priv->clk); | 123 | *f = clk_get_rate(priv->clk); |
| 124 | |||
| 125 | /* enable 16bit data access on SDBUF as default */ | ||
| 126 | sh_mobile_sdhi_sdbuf_width(host, 16); | ||
| 127 | |||
| 97 | return 0; | 128 | return 0; |
| 98 | } | 129 | } |
| 99 | 130 | ||
| @@ -101,7 +132,7 @@ static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev) | |||
| 101 | { | 132 | { |
| 102 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 133 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 103 | struct tmio_mmc_host *host = mmc_priv(mmc); | 134 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 104 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); | 135 | struct sh_mobile_sdhi *priv = host_to_priv(host); |
| 105 | clk_disable_unprepare(priv->clk); | 136 | clk_disable_unprepare(priv->clk); |
| 106 | } | 137 | } |
| 107 | 138 | ||
| @@ -113,7 +144,7 @@ static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) | |||
| 113 | udelay(1); | 144 | udelay(1); |
| 114 | 145 | ||
| 115 | if (!timeout) { | 146 | if (!timeout) { |
| 116 | dev_warn(host->pdata->dev, "timeout waiting for SD bus idle\n"); | 147 | dev_warn(&host->pdev->dev, "timeout waiting for SD bus idle\n"); |
| 117 | return -EBUSY; | 148 | return -EBUSY; |
| 118 | } | 149 | } |
| 119 | 150 | ||
| @@ -156,14 +187,13 @@ static int sh_mobile_sdhi_multi_io_quirk(struct mmc_card *card, | |||
| 156 | return blk_size; | 187 | return blk_size; |
| 157 | } | 188 | } |
| 158 | 189 | ||
| 159 | static void sh_mobile_sdhi_cd_wakeup(const struct platform_device *pdev) | 190 | static void sh_mobile_sdhi_enable_dma(struct tmio_mmc_host *host, bool enable) |
| 160 | { | 191 | { |
| 161 | mmc_detect_change(platform_get_drvdata(pdev), msecs_to_jiffies(100)); | 192 | sd_ctrl_write16(host, CTL_DMA_ENABLE, enable ? 2 : 0); |
| 162 | } | ||
| 163 | 193 | ||
| 164 | static const struct sh_mobile_sdhi_ops sdhi_ops = { | 194 | /* enable 32bit access if DMA mode if possibile */ |
| 165 | .cd_wakeup = sh_mobile_sdhi_cd_wakeup, | 195 | sh_mobile_sdhi_sdbuf_width(host, enable ? 32 : 16); |
| 166 | }; | 196 | } |
| 167 | 197 | ||
| 168 | static int sh_mobile_sdhi_probe(struct platform_device *pdev) | 198 | static int sh_mobile_sdhi_probe(struct platform_device *pdev) |
| 169 | { | 199 | { |
| @@ -177,7 +207,6 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 177 | int irq, ret, i = 0; | 207 | int irq, ret, i = 0; |
| 178 | bool multiplexed_isr = true; | 208 | bool multiplexed_isr = true; |
| 179 | struct tmio_mmc_dma *dma_priv; | 209 | struct tmio_mmc_dma *dma_priv; |
| 180 | u16 ver; | ||
| 181 | 210 | ||
| 182 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 211 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 183 | if (!res) | 212 | if (!res) |
| @@ -192,26 +221,31 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 192 | mmc_data = &priv->mmc_data; | 221 | mmc_data = &priv->mmc_data; |
| 193 | dma_priv = &priv->dma_priv; | 222 | dma_priv = &priv->dma_priv; |
| 194 | 223 | ||
| 195 | if (p) { | ||
| 196 | if (p->init) { | ||
| 197 | ret = p->init(pdev, &sdhi_ops); | ||
| 198 | if (ret) | ||
| 199 | return ret; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | priv->clk = devm_clk_get(&pdev->dev, NULL); | 224 | priv->clk = devm_clk_get(&pdev->dev, NULL); |
| 204 | if (IS_ERR(priv->clk)) { | 225 | if (IS_ERR(priv->clk)) { |
| 205 | ret = PTR_ERR(priv->clk); | 226 | ret = PTR_ERR(priv->clk); |
| 206 | dev_err(&pdev->dev, "cannot get clock: %d\n", ret); | 227 | dev_err(&pdev->dev, "cannot get clock: %d\n", ret); |
| 207 | goto eclkget; | 228 | goto eprobe; |
| 208 | } | 229 | } |
| 209 | 230 | ||
| 210 | mmc_data->clk_enable = sh_mobile_sdhi_clk_enable; | 231 | host = tmio_mmc_host_alloc(pdev); |
| 211 | mmc_data->clk_disable = sh_mobile_sdhi_clk_disable; | 232 | if (!host) { |
| 233 | ret = -ENOMEM; | ||
| 234 | goto eprobe; | ||
| 235 | } | ||
| 236 | |||
| 237 | host->dma = dma_priv; | ||
| 238 | host->write16_hook = sh_mobile_sdhi_write16_hook; | ||
| 239 | host->clk_enable = sh_mobile_sdhi_clk_enable; | ||
| 240 | host->clk_disable = sh_mobile_sdhi_clk_disable; | ||
| 241 | host->multi_io_quirk = sh_mobile_sdhi_multi_io_quirk; | ||
| 242 | /* SD control register space size is 0x100, 0x200 for bus_shift=1 */ | ||
| 243 | if (resource_size(res) > 0x100) | ||
| 244 | host->bus_shift = 1; | ||
| 245 | else | ||
| 246 | host->bus_shift = 0; | ||
| 247 | |||
| 212 | mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; | 248 | mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED; |
| 213 | mmc_data->write16_hook = sh_mobile_sdhi_write16_hook; | ||
| 214 | mmc_data->multi_io_quirk = sh_mobile_sdhi_multi_io_quirk; | ||
| 215 | if (p) { | 249 | if (p) { |
| 216 | mmc_data->flags = p->tmio_flags; | 250 | mmc_data->flags = p->tmio_flags; |
| 217 | mmc_data->ocr_mask = p->tmio_ocr_mask; | 251 | mmc_data->ocr_mask = p->tmio_ocr_mask; |
| @@ -231,11 +265,10 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 231 | dma_priv->slave_id_rx = p->dma_slave_rx; | 265 | dma_priv->slave_id_rx = p->dma_slave_rx; |
| 232 | } | 266 | } |
| 233 | } | 267 | } |
| 234 | |||
| 235 | dma_priv->alignment_shift = 1; /* 2-byte alignment */ | ||
| 236 | dma_priv->filter = shdma_chan_filter; | 268 | dma_priv->filter = shdma_chan_filter; |
| 269 | dma_priv->enable = sh_mobile_sdhi_enable_dma; | ||
| 237 | 270 | ||
| 238 | mmc_data->dma = dma_priv; | 271 | mmc_data->alignment_shift = 1; /* 2-byte alignment */ |
| 239 | 272 | ||
| 240 | /* | 273 | /* |
| 241 | * All SDHI blocks support 2-byte and larger block sizes in 4-bit | 274 | * All SDHI blocks support 2-byte and larger block sizes in 4-bit |
| @@ -258,33 +291,18 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 258 | */ | 291 | */ |
| 259 | mmc_data->flags |= TMIO_MMC_SDIO_STATUS_QUIRK; | 292 | mmc_data->flags |= TMIO_MMC_SDIO_STATUS_QUIRK; |
| 260 | 293 | ||
| 261 | /* | ||
| 262 | * All SDHI have DMA control register | ||
| 263 | */ | ||
| 264 | mmc_data->flags |= TMIO_MMC_HAVE_CTL_DMA_REG; | ||
| 265 | |||
| 266 | if (of_id && of_id->data) { | 294 | if (of_id && of_id->data) { |
| 267 | const struct sh_mobile_sdhi_of_data *of_data = of_id->data; | 295 | const struct sh_mobile_sdhi_of_data *of_data = of_id->data; |
| 268 | mmc_data->flags |= of_data->tmio_flags; | 296 | mmc_data->flags |= of_data->tmio_flags; |
| 269 | mmc_data->capabilities |= of_data->capabilities; | 297 | mmc_data->capabilities |= of_data->capabilities; |
| 270 | mmc_data->capabilities2 |= of_data->capabilities2; | 298 | mmc_data->capabilities2 |= of_data->capabilities2; |
| 271 | dma_priv->dma_rx_offset = of_data->dma_rx_offset; | 299 | mmc_data->dma_rx_offset = of_data->dma_rx_offset; |
| 300 | dma_priv->dma_buswidth = of_data->dma_buswidth; | ||
| 272 | } | 301 | } |
| 273 | 302 | ||
| 274 | /* SD control register space size is 0x100, 0x200 for bus_shift=1 */ | 303 | ret = tmio_mmc_host_probe(host, mmc_data); |
| 275 | mmc_data->bus_shift = resource_size(res) >> 9; | ||
| 276 | |||
| 277 | ret = tmio_mmc_host_probe(&host, pdev, mmc_data); | ||
| 278 | if (ret < 0) | 304 | if (ret < 0) |
| 279 | goto eprobe; | 305 | goto efree; |
| 280 | |||
| 281 | /* | ||
| 282 | * FIXME: | ||
| 283 | * this Workaround can be more clever method | ||
| 284 | */ | ||
| 285 | ver = sd_ctrl_read16(host, CTL_VERSION); | ||
| 286 | if (ver == 0xCB0D) | ||
| 287 | sd_ctrl_write16(host, EXT_ACC, 1); | ||
| 288 | 306 | ||
| 289 | /* | 307 | /* |
| 290 | * Allow one or more specific (named) ISRs or | 308 | * Allow one or more specific (named) ISRs or |
| @@ -351,10 +369,9 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 351 | 369 | ||
| 352 | eirq: | 370 | eirq: |
| 353 | tmio_mmc_host_remove(host); | 371 | tmio_mmc_host_remove(host); |
| 372 | efree: | ||
| 373 | tmio_mmc_host_free(host); | ||
| 354 | eprobe: | 374 | eprobe: |
| 355 | eclkget: | ||
| 356 | if (p && p->cleanup) | ||
| 357 | p->cleanup(pdev); | ||
| 358 | return ret; | 375 | return ret; |
| 359 | } | 376 | } |
| 360 | 377 | ||
| @@ -362,13 +379,9 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev) | |||
| 362 | { | 379 | { |
| 363 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 380 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 364 | struct tmio_mmc_host *host = mmc_priv(mmc); | 381 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 365 | struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; | ||
| 366 | 382 | ||
| 367 | tmio_mmc_host_remove(host); | 383 | tmio_mmc_host_remove(host); |
| 368 | 384 | ||
| 369 | if (p && p->cleanup) | ||
| 370 | p->cleanup(pdev); | ||
| 371 | |||
| 372 | return 0; | 385 | return 0; |
| 373 | } | 386 | } |
| 374 | 387 | ||
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 15cb8b7ffc34..6af0a28ba37d 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c | |||
| @@ -252,7 +252,7 @@ static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host) | |||
| 252 | unsigned long expire = jiffies + msecs_to_jiffies(250); | 252 | unsigned long expire = jiffies + msecs_to_jiffies(250); |
| 253 | u32 rval; | 253 | u32 rval; |
| 254 | 254 | ||
| 255 | mmc_writel(host, REG_CMDR, SDXC_HARDWARE_RESET); | 255 | mmc_writel(host, REG_GCTRL, SDXC_HARDWARE_RESET); |
| 256 | do { | 256 | do { |
| 257 | rval = mmc_readl(host, REG_GCTRL); | 257 | rval = mmc_readl(host, REG_GCTRL); |
| 258 | } while (time_before(jiffies, expire) && (rval & SDXC_HARDWARE_RESET)); | 258 | } while (time_before(jiffies, expire) && (rval & SDXC_HARDWARE_RESET)); |
| @@ -310,7 +310,9 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, | |||
| 310 | } | 310 | } |
| 311 | 311 | ||
| 312 | pdes[0].config |= SDXC_IDMAC_DES0_FD; | 312 | pdes[0].config |= SDXC_IDMAC_DES0_FD; |
| 313 | pdes[i - 1].config = SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_LD; | 313 | pdes[i - 1].config |= SDXC_IDMAC_DES0_LD | SDXC_IDMAC_DES0_ER; |
| 314 | pdes[i - 1].config &= ~SDXC_IDMAC_DES0_DIC; | ||
| 315 | pdes[i - 1].buf_addr_ptr2 = 0; | ||
| 314 | 316 | ||
| 315 | /* | 317 | /* |
| 316 | * Avoid the io-store starting the idmac hitting io-mem before the | 318 | * Avoid the io-store starting the idmac hitting io-mem before the |
| @@ -570,6 +572,15 @@ static irqreturn_t sunxi_mmc_handle_manual_stop(int irq, void *dev_id) | |||
| 570 | } | 572 | } |
| 571 | 573 | ||
| 572 | dev_err(mmc_dev(host->mmc), "data error, sending stop command\n"); | 574 | dev_err(mmc_dev(host->mmc), "data error, sending stop command\n"); |
| 575 | |||
| 576 | /* | ||
| 577 | * We will never have more than one outstanding request, | ||
| 578 | * and we do not complete the request until after | ||
| 579 | * we've cleared host->manual_stop_mrq so we do not need to | ||
| 580 | * spin lock this function. | ||
| 581 | * Additionally we have wait states within this function | ||
| 582 | * so having it in a lock is a very bad idea. | ||
| 583 | */ | ||
| 573 | sunxi_mmc_send_manual_stop(host, mrq); | 584 | sunxi_mmc_send_manual_stop(host, mrq); |
| 574 | 585 | ||
| 575 | spin_lock_irqsave(&host->lock, iflags); | 586 | spin_lock_irqsave(&host->lock, iflags); |
| @@ -616,7 +627,7 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en) | |||
| 616 | static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, | 627 | static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, |
| 617 | struct mmc_ios *ios) | 628 | struct mmc_ios *ios) |
| 618 | { | 629 | { |
| 619 | u32 rate, oclk_dly, rval, sclk_dly, src_clk; | 630 | u32 rate, oclk_dly, rval, sclk_dly; |
| 620 | int ret; | 631 | int ret; |
| 621 | 632 | ||
| 622 | rate = clk_round_rate(host->clk_mmc, ios->clock); | 633 | rate = clk_round_rate(host->clk_mmc, ios->clock); |
| @@ -661,14 +672,6 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, | |||
| 661 | sclk_dly = 4; | 672 | sclk_dly = 4; |
| 662 | } | 673 | } |
| 663 | 674 | ||
| 664 | src_clk = clk_get_rate(clk_get_parent(host->clk_mmc)); | ||
| 665 | if (src_clk >= 300000000 && src_clk <= 400000000) { | ||
| 666 | if (oclk_dly) | ||
| 667 | oclk_dly--; | ||
| 668 | if (sclk_dly) | ||
| 669 | sclk_dly--; | ||
| 670 | } | ||
| 671 | |||
| 672 | clk_sunxi_mmc_phase_control(host->clk_mmc, sclk_dly, oclk_dly); | 675 | clk_sunxi_mmc_phase_control(host->clk_mmc, sclk_dly, oclk_dly); |
| 673 | 676 | ||
| 674 | return sunxi_mmc_oclk_onoff(host, 1); | 677 | return sunxi_mmc_oclk_onoff(host, 1); |
| @@ -766,6 +769,7 @@ static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 766 | unsigned long iflags; | 769 | unsigned long iflags; |
| 767 | u32 imask = SDXC_INTERRUPT_ERROR_BIT; | 770 | u32 imask = SDXC_INTERRUPT_ERROR_BIT; |
| 768 | u32 cmd_val = SDXC_START | (cmd->opcode & 0x3f); | 771 | u32 cmd_val = SDXC_START | (cmd->opcode & 0x3f); |
| 772 | bool wait_dma = host->wait_dma; | ||
| 769 | int ret; | 773 | int ret; |
| 770 | 774 | ||
| 771 | /* Check for set_ios errors (should never happen) */ | 775 | /* Check for set_ios errors (should never happen) */ |
| @@ -816,7 +820,7 @@ static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 816 | if (cmd->data->flags & MMC_DATA_WRITE) | 820 | if (cmd->data->flags & MMC_DATA_WRITE) |
| 817 | cmd_val |= SDXC_WRITE; | 821 | cmd_val |= SDXC_WRITE; |
| 818 | else | 822 | else |
| 819 | host->wait_dma = true; | 823 | wait_dma = true; |
| 820 | } else { | 824 | } else { |
| 821 | imask |= SDXC_COMMAND_DONE; | 825 | imask |= SDXC_COMMAND_DONE; |
| 822 | } | 826 | } |
| @@ -850,6 +854,7 @@ static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 850 | } | 854 | } |
| 851 | 855 | ||
| 852 | host->mrq = mrq; | 856 | host->mrq = mrq; |
| 857 | host->wait_dma = wait_dma; | ||
| 853 | mmc_writel(host, REG_IMASK, host->sdio_imask | imask); | 858 | mmc_writel(host, REG_IMASK, host->sdio_imask | imask); |
| 854 | mmc_writel(host, REG_CARG, cmd->arg); | 859 | mmc_writel(host, REG_CARG, cmd->arg); |
| 855 | mmc_writel(host, REG_CMDR, cmd_val); | 860 | mmc_writel(host, REG_CMDR, cmd_val); |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 2ca0afaab792..f746df493892 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
| @@ -88,14 +88,19 @@ static int tmio_mmc_probe(struct platform_device *pdev) | |||
| 88 | if (!res) | 88 | if (!res) |
| 89 | return -EINVAL; | 89 | return -EINVAL; |
| 90 | 90 | ||
| 91 | /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ | ||
| 92 | pdata->bus_shift = resource_size(res) >> 10; | ||
| 93 | pdata->flags |= TMIO_MMC_HAVE_HIGH_REG; | 91 | pdata->flags |= TMIO_MMC_HAVE_HIGH_REG; |
| 94 | 92 | ||
| 95 | ret = tmio_mmc_host_probe(&host, pdev, pdata); | 93 | host = tmio_mmc_host_alloc(pdev); |
| 96 | if (ret) | 94 | if (!host) |
| 97 | goto cell_disable; | 95 | goto cell_disable; |
| 98 | 96 | ||
| 97 | /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ | ||
| 98 | host->bus_shift = resource_size(res) >> 10; | ||
| 99 | |||
| 100 | ret = tmio_mmc_host_probe(host, pdata); | ||
| 101 | if (ret) | ||
| 102 | goto host_free; | ||
| 103 | |||
| 99 | ret = request_irq(irq, tmio_mmc_irq, IRQF_TRIGGER_FALLING, | 104 | ret = request_irq(irq, tmio_mmc_irq, IRQF_TRIGGER_FALLING, |
| 100 | dev_name(&pdev->dev), host); | 105 | dev_name(&pdev->dev), host); |
| 101 | if (ret) | 106 | if (ret) |
| @@ -108,6 +113,8 @@ static int tmio_mmc_probe(struct platform_device *pdev) | |||
| 108 | 113 | ||
| 109 | host_remove: | 114 | host_remove: |
| 110 | tmio_mmc_host_remove(host); | 115 | tmio_mmc_host_remove(host); |
| 116 | host_free: | ||
| 117 | tmio_mmc_host_free(host); | ||
| 111 | cell_disable: | 118 | cell_disable: |
| 112 | if (cell->disable) | 119 | if (cell->disable) |
| 113 | cell->disable(pdev); | 120 | cell->disable(pdev); |
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index a34ecbe1c1ad..fc3805ed69d1 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #ifndef TMIO_MMC_H | 16 | #ifndef TMIO_MMC_H |
| 17 | #define TMIO_MMC_H | 17 | #define TMIO_MMC_H |
| 18 | 18 | ||
| 19 | #include <linux/dmaengine.h> | ||
| 19 | #include <linux/highmem.h> | 20 | #include <linux/highmem.h> |
| 20 | #include <linux/mmc/tmio.h> | 21 | #include <linux/mmc/tmio.h> |
| 21 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
| @@ -39,6 +40,17 @@ | |||
| 39 | #define TMIO_MASK_IRQ (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD) | 40 | #define TMIO_MASK_IRQ (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD) |
| 40 | 41 | ||
| 41 | struct tmio_mmc_data; | 42 | struct tmio_mmc_data; |
| 43 | struct tmio_mmc_host; | ||
| 44 | |||
| 45 | struct tmio_mmc_dma { | ||
| 46 | void *chan_priv_tx; | ||
| 47 | void *chan_priv_rx; | ||
| 48 | int slave_id_tx; | ||
| 49 | int slave_id_rx; | ||
| 50 | enum dma_slave_buswidth dma_buswidth; | ||
| 51 | bool (*filter)(struct dma_chan *chan, void *arg); | ||
| 52 | void (*enable)(struct tmio_mmc_host *host, bool enable); | ||
| 53 | }; | ||
| 42 | 54 | ||
| 43 | struct tmio_mmc_host { | 55 | struct tmio_mmc_host { |
| 44 | void __iomem *ctl; | 56 | void __iomem *ctl; |
| @@ -56,9 +68,11 @@ struct tmio_mmc_host { | |||
| 56 | struct scatterlist *sg_orig; | 68 | struct scatterlist *sg_orig; |
| 57 | unsigned int sg_len; | 69 | unsigned int sg_len; |
| 58 | unsigned int sg_off; | 70 | unsigned int sg_off; |
| 71 | unsigned long bus_shift; | ||
| 59 | 72 | ||
| 60 | struct platform_device *pdev; | 73 | struct platform_device *pdev; |
| 61 | struct tmio_mmc_data *pdata; | 74 | struct tmio_mmc_data *pdata; |
| 75 | struct tmio_mmc_dma *dma; | ||
| 62 | 76 | ||
| 63 | /* DMA support */ | 77 | /* DMA support */ |
| 64 | bool force_pio; | 78 | bool force_pio; |
| @@ -83,10 +97,17 @@ struct tmio_mmc_host { | |||
| 83 | struct mutex ios_lock; /* protect set_ios() context */ | 97 | struct mutex ios_lock; /* protect set_ios() context */ |
| 84 | bool native_hotplug; | 98 | bool native_hotplug; |
| 85 | bool sdio_irq_enabled; | 99 | bool sdio_irq_enabled; |
| 100 | |||
| 101 | int (*write16_hook)(struct tmio_mmc_host *host, int addr); | ||
| 102 | int (*clk_enable)(struct platform_device *pdev, unsigned int *f); | ||
| 103 | void (*clk_disable)(struct platform_device *pdev); | ||
| 104 | int (*multi_io_quirk)(struct mmc_card *card, | ||
| 105 | unsigned int direction, int blk_size); | ||
| 86 | }; | 106 | }; |
| 87 | 107 | ||
| 88 | int tmio_mmc_host_probe(struct tmio_mmc_host **host, | 108 | struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev); |
| 89 | struct platform_device *pdev, | 109 | void tmio_mmc_host_free(struct tmio_mmc_host *host); |
| 110 | int tmio_mmc_host_probe(struct tmio_mmc_host *host, | ||
| 90 | struct tmio_mmc_data *pdata); | 111 | struct tmio_mmc_data *pdata); |
| 91 | void tmio_mmc_host_remove(struct tmio_mmc_host *host); | 112 | void tmio_mmc_host_remove(struct tmio_mmc_host *host); |
| 92 | void tmio_mmc_do_data_irq(struct tmio_mmc_host *host); | 113 | void tmio_mmc_do_data_irq(struct tmio_mmc_host *host); |
| @@ -151,19 +172,19 @@ int tmio_mmc_host_runtime_resume(struct device *dev); | |||
| 151 | 172 | ||
| 152 | static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) | 173 | static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) |
| 153 | { | 174 | { |
| 154 | return readw(host->ctl + (addr << host->pdata->bus_shift)); | 175 | return readw(host->ctl + (addr << host->bus_shift)); |
| 155 | } | 176 | } |
| 156 | 177 | ||
| 157 | static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr, | 178 | static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr, |
| 158 | u16 *buf, int count) | 179 | u16 *buf, int count) |
| 159 | { | 180 | { |
| 160 | readsw(host->ctl + (addr << host->pdata->bus_shift), buf, count); | 181 | readsw(host->ctl + (addr << host->bus_shift), buf, count); |
| 161 | } | 182 | } |
| 162 | 183 | ||
| 163 | static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) | 184 | static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) |
| 164 | { | 185 | { |
| 165 | return readw(host->ctl + (addr << host->pdata->bus_shift)) | | 186 | return readw(host->ctl + (addr << host->bus_shift)) | |
| 166 | readw(host->ctl + ((addr + 2) << host->pdata->bus_shift)) << 16; | 187 | readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16; |
| 167 | } | 188 | } |
| 168 | 189 | ||
| 169 | static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val) | 190 | static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val) |
| @@ -171,21 +192,21 @@ static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val | |||
| 171 | /* If there is a hook and it returns non-zero then there | 192 | /* If there is a hook and it returns non-zero then there |
| 172 | * is an error and the write should be skipped | 193 | * is an error and the write should be skipped |
| 173 | */ | 194 | */ |
| 174 | if (host->pdata->write16_hook && host->pdata->write16_hook(host, addr)) | 195 | if (host->write16_hook && host->write16_hook(host, addr)) |
| 175 | return; | 196 | return; |
| 176 | writew(val, host->ctl + (addr << host->pdata->bus_shift)); | 197 | writew(val, host->ctl + (addr << host->bus_shift)); |
| 177 | } | 198 | } |
| 178 | 199 | ||
| 179 | static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, | 200 | static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, |
| 180 | u16 *buf, int count) | 201 | u16 *buf, int count) |
| 181 | { | 202 | { |
| 182 | writesw(host->ctl + (addr << host->pdata->bus_shift), buf, count); | 203 | writesw(host->ctl + (addr << host->bus_shift), buf, count); |
| 183 | } | 204 | } |
| 184 | 205 | ||
| 185 | static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val) | 206 | static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val) |
| 186 | { | 207 | { |
| 187 | writew(val, host->ctl + (addr << host->pdata->bus_shift)); | 208 | writew(val, host->ctl + (addr << host->bus_shift)); |
| 188 | writew(val >> 16, host->ctl + ((addr + 2) << host->pdata->bus_shift)); | 209 | writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); |
| 189 | } | 210 | } |
| 190 | 211 | ||
| 191 | 212 | ||
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index 7d077388b9eb..331bb618e398 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c | |||
| @@ -28,8 +28,8 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) | |||
| 28 | if (!host->chan_tx || !host->chan_rx) | 28 | if (!host->chan_tx || !host->chan_rx) |
| 29 | return; | 29 | return; |
| 30 | 30 | ||
| 31 | if (host->pdata->flags & TMIO_MMC_HAVE_CTL_DMA_REG) | 31 | if (host->dma->enable) |
| 32 | sd_ctrl_write16(host, CTL_DMA_ENABLE, enable ? 2 : 0); | 32 | host->dma->enable(host, enable); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | void tmio_mmc_abort_dma(struct tmio_mmc_host *host) | 35 | void tmio_mmc_abort_dma(struct tmio_mmc_host *host) |
| @@ -49,11 +49,10 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) | |||
| 49 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; | 49 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; |
| 50 | struct dma_async_tx_descriptor *desc = NULL; | 50 | struct dma_async_tx_descriptor *desc = NULL; |
| 51 | struct dma_chan *chan = host->chan_rx; | 51 | struct dma_chan *chan = host->chan_rx; |
| 52 | struct tmio_mmc_data *pdata = host->pdata; | ||
| 53 | dma_cookie_t cookie; | 52 | dma_cookie_t cookie; |
| 54 | int ret, i; | 53 | int ret, i; |
| 55 | bool aligned = true, multiple = true; | 54 | bool aligned = true, multiple = true; |
| 56 | unsigned int align = (1 << pdata->dma->alignment_shift) - 1; | 55 | unsigned int align = (1 << host->pdata->alignment_shift) - 1; |
| 57 | 56 | ||
| 58 | for_each_sg(sg, sg_tmp, host->sg_len, i) { | 57 | for_each_sg(sg, sg_tmp, host->sg_len, i) { |
| 59 | if (sg_tmp->offset & align) | 58 | if (sg_tmp->offset & align) |
| @@ -126,11 +125,10 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) | |||
| 126 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; | 125 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; |
| 127 | struct dma_async_tx_descriptor *desc = NULL; | 126 | struct dma_async_tx_descriptor *desc = NULL; |
| 128 | struct dma_chan *chan = host->chan_tx; | 127 | struct dma_chan *chan = host->chan_tx; |
| 129 | struct tmio_mmc_data *pdata = host->pdata; | ||
| 130 | dma_cookie_t cookie; | 128 | dma_cookie_t cookie; |
| 131 | int ret, i; | 129 | int ret, i; |
| 132 | bool aligned = true, multiple = true; | 130 | bool aligned = true, multiple = true; |
| 133 | unsigned int align = (1 << pdata->dma->alignment_shift) - 1; | 131 | unsigned int align = (1 << host->pdata->alignment_shift) - 1; |
| 134 | 132 | ||
| 135 | for_each_sg(sg, sg_tmp, host->sg_len, i) { | 133 | for_each_sg(sg, sg_tmp, host->sg_len, i) { |
| 136 | if (sg_tmp->offset & align) | 134 | if (sg_tmp->offset & align) |
| @@ -262,8 +260,8 @@ out: | |||
| 262 | void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata) | 260 | void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata) |
| 263 | { | 261 | { |
| 264 | /* We can only either use DMA for both Tx and Rx or not use it at all */ | 262 | /* We can only either use DMA for both Tx and Rx or not use it at all */ |
| 265 | if (!pdata->dma || (!host->pdev->dev.of_node && | 263 | if (!host->dma || (!host->pdev->dev.of_node && |
| 266 | (!pdata->dma->chan_priv_tx || !pdata->dma->chan_priv_rx))) | 264 | (!host->dma->chan_priv_tx || !host->dma->chan_priv_rx))) |
| 267 | return; | 265 | return; |
| 268 | 266 | ||
| 269 | if (!host->chan_tx && !host->chan_rx) { | 267 | if (!host->chan_tx && !host->chan_rx) { |
| @@ -280,7 +278,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat | |||
| 280 | dma_cap_set(DMA_SLAVE, mask); | 278 | dma_cap_set(DMA_SLAVE, mask); |
| 281 | 279 | ||
| 282 | host->chan_tx = dma_request_slave_channel_compat(mask, | 280 | host->chan_tx = dma_request_slave_channel_compat(mask, |
| 283 | pdata->dma->filter, pdata->dma->chan_priv_tx, | 281 | host->dma->filter, host->dma->chan_priv_tx, |
| 284 | &host->pdev->dev, "tx"); | 282 | &host->pdev->dev, "tx"); |
| 285 | dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__, | 283 | dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__, |
| 286 | host->chan_tx); | 284 | host->chan_tx); |
| @@ -288,18 +286,20 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat | |||
| 288 | if (!host->chan_tx) | 286 | if (!host->chan_tx) |
| 289 | return; | 287 | return; |
| 290 | 288 | ||
| 291 | if (pdata->dma->chan_priv_tx) | 289 | if (host->dma->chan_priv_tx) |
| 292 | cfg.slave_id = pdata->dma->slave_id_tx; | 290 | cfg.slave_id = host->dma->slave_id_tx; |
| 293 | cfg.direction = DMA_MEM_TO_DEV; | 291 | cfg.direction = DMA_MEM_TO_DEV; |
| 294 | cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->pdata->bus_shift); | 292 | cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->bus_shift); |
| 295 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | 293 | cfg.dst_addr_width = host->dma->dma_buswidth; |
| 294 | if (!cfg.dst_addr_width) | ||
| 295 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
| 296 | cfg.src_addr = 0; | 296 | cfg.src_addr = 0; |
| 297 | ret = dmaengine_slave_config(host->chan_tx, &cfg); | 297 | ret = dmaengine_slave_config(host->chan_tx, &cfg); |
| 298 | if (ret < 0) | 298 | if (ret < 0) |
| 299 | goto ecfgtx; | 299 | goto ecfgtx; |
| 300 | 300 | ||
| 301 | host->chan_rx = dma_request_slave_channel_compat(mask, | 301 | host->chan_rx = dma_request_slave_channel_compat(mask, |
| 302 | pdata->dma->filter, pdata->dma->chan_priv_rx, | 302 | host->dma->filter, host->dma->chan_priv_rx, |
| 303 | &host->pdev->dev, "rx"); | 303 | &host->pdev->dev, "rx"); |
| 304 | dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__, | 304 | dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__, |
| 305 | host->chan_rx); | 305 | host->chan_rx); |
| @@ -307,11 +307,13 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat | |||
| 307 | if (!host->chan_rx) | 307 | if (!host->chan_rx) |
| 308 | goto ereqrx; | 308 | goto ereqrx; |
| 309 | 309 | ||
| 310 | if (pdata->dma->chan_priv_rx) | 310 | if (host->dma->chan_priv_rx) |
| 311 | cfg.slave_id = pdata->dma->slave_id_rx; | 311 | cfg.slave_id = host->dma->slave_id_rx; |
| 312 | cfg.direction = DMA_DEV_TO_MEM; | 312 | cfg.direction = DMA_DEV_TO_MEM; |
| 313 | cfg.src_addr = cfg.dst_addr + pdata->dma->dma_rx_offset; | 313 | cfg.src_addr = cfg.dst_addr + host->pdata->dma_rx_offset; |
| 314 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | 314 | cfg.src_addr_width = host->dma->dma_buswidth; |
| 315 | if (!cfg.src_addr_width) | ||
| 316 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
| 315 | cfg.dst_addr = 0; | 317 | cfg.dst_addr = 0; |
| 316 | ret = dmaengine_slave_config(host->chan_rx, &cfg); | 318 | ret = dmaengine_slave_config(host->chan_rx, &cfg); |
| 317 | if (ret < 0) | 319 | if (ret < 0) |
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 250bf8c9f998..a31c3573d386 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
| @@ -835,13 +835,12 @@ fail: | |||
| 835 | static int tmio_mmc_clk_update(struct tmio_mmc_host *host) | 835 | static int tmio_mmc_clk_update(struct tmio_mmc_host *host) |
| 836 | { | 836 | { |
| 837 | struct mmc_host *mmc = host->mmc; | 837 | struct mmc_host *mmc = host->mmc; |
| 838 | struct tmio_mmc_data *pdata = host->pdata; | ||
| 839 | int ret; | 838 | int ret; |
| 840 | 839 | ||
| 841 | if (!pdata->clk_enable) | 840 | if (!host->clk_enable) |
| 842 | return -ENOTSUPP; | 841 | return -ENOTSUPP; |
| 843 | 842 | ||
| 844 | ret = pdata->clk_enable(host->pdev, &mmc->f_max); | 843 | ret = host->clk_enable(host->pdev, &mmc->f_max); |
| 845 | if (!ret) | 844 | if (!ret) |
| 846 | mmc->f_min = mmc->f_max / 512; | 845 | mmc->f_min = mmc->f_max / 512; |
| 847 | 846 | ||
| @@ -1005,10 +1004,9 @@ static int tmio_multi_io_quirk(struct mmc_card *card, | |||
| 1005 | unsigned int direction, int blk_size) | 1004 | unsigned int direction, int blk_size) |
| 1006 | { | 1005 | { |
| 1007 | struct tmio_mmc_host *host = mmc_priv(card->host); | 1006 | struct tmio_mmc_host *host = mmc_priv(card->host); |
| 1008 | struct tmio_mmc_data *pdata = host->pdata; | ||
| 1009 | 1007 | ||
| 1010 | if (pdata->multi_io_quirk) | 1008 | if (host->multi_io_quirk) |
| 1011 | return pdata->multi_io_quirk(card, direction, blk_size); | 1009 | return host->multi_io_quirk(card, direction, blk_size); |
| 1012 | 1010 | ||
| 1013 | return blk_size; | 1011 | return blk_size; |
| 1014 | } | 1012 | } |
| @@ -1054,12 +1052,37 @@ static void tmio_mmc_of_parse(struct platform_device *pdev, | |||
| 1054 | pdata->flags |= TMIO_MMC_WRPROTECT_DISABLE; | 1052 | pdata->flags |= TMIO_MMC_WRPROTECT_DISABLE; |
| 1055 | } | 1053 | } |
| 1056 | 1054 | ||
| 1057 | int tmio_mmc_host_probe(struct tmio_mmc_host **host, | 1055 | struct tmio_mmc_host* |
| 1058 | struct platform_device *pdev, | 1056 | tmio_mmc_host_alloc(struct platform_device *pdev) |
| 1059 | struct tmio_mmc_data *pdata) | ||
| 1060 | { | 1057 | { |
| 1061 | struct tmio_mmc_host *_host; | 1058 | struct tmio_mmc_host *host; |
| 1062 | struct mmc_host *mmc; | 1059 | struct mmc_host *mmc; |
| 1060 | |||
| 1061 | mmc = mmc_alloc_host(sizeof(struct tmio_mmc_host), &pdev->dev); | ||
| 1062 | if (!mmc) | ||
| 1063 | return NULL; | ||
| 1064 | |||
| 1065 | host = mmc_priv(mmc); | ||
| 1066 | host->mmc = mmc; | ||
| 1067 | host->pdev = pdev; | ||
| 1068 | |||
| 1069 | return host; | ||
| 1070 | } | ||
| 1071 | EXPORT_SYMBOL(tmio_mmc_host_alloc); | ||
| 1072 | |||
| 1073 | void tmio_mmc_host_free(struct tmio_mmc_host *host) | ||
| 1074 | { | ||
| 1075 | mmc_free_host(host->mmc); | ||
| 1076 | |||
| 1077 | host->mmc = NULL; | ||
| 1078 | } | ||
| 1079 | EXPORT_SYMBOL(tmio_mmc_host_free); | ||
| 1080 | |||
| 1081 | int tmio_mmc_host_probe(struct tmio_mmc_host *_host, | ||
| 1082 | struct tmio_mmc_data *pdata) | ||
| 1083 | { | ||
| 1084 | struct platform_device *pdev = _host->pdev; | ||
| 1085 | struct mmc_host *mmc = _host->mmc; | ||
| 1063 | struct resource *res_ctl; | 1086 | struct resource *res_ctl; |
| 1064 | int ret; | 1087 | int ret; |
| 1065 | u32 irq_mask = TMIO_MASK_CMD; | 1088 | u32 irq_mask = TMIO_MASK_CMD; |
| @@ -1067,25 +1090,17 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
| 1067 | tmio_mmc_of_parse(pdev, pdata); | 1090 | tmio_mmc_of_parse(pdev, pdata); |
| 1068 | 1091 | ||
| 1069 | if (!(pdata->flags & TMIO_MMC_HAS_IDLE_WAIT)) | 1092 | if (!(pdata->flags & TMIO_MMC_HAS_IDLE_WAIT)) |
| 1070 | pdata->write16_hook = NULL; | 1093 | _host->write16_hook = NULL; |
| 1071 | 1094 | ||
| 1072 | res_ctl = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1095 | res_ctl = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1073 | if (!res_ctl) | 1096 | if (!res_ctl) |
| 1074 | return -EINVAL; | 1097 | return -EINVAL; |
| 1075 | 1098 | ||
| 1076 | mmc = mmc_alloc_host(sizeof(struct tmio_mmc_host), &pdev->dev); | ||
| 1077 | if (!mmc) | ||
| 1078 | return -ENOMEM; | ||
| 1079 | |||
| 1080 | ret = mmc_of_parse(mmc); | 1099 | ret = mmc_of_parse(mmc); |
| 1081 | if (ret < 0) | 1100 | if (ret < 0) |
| 1082 | goto host_free; | 1101 | goto host_free; |
| 1083 | 1102 | ||
| 1084 | pdata->dev = &pdev->dev; | ||
| 1085 | _host = mmc_priv(mmc); | ||
| 1086 | _host->pdata = pdata; | 1103 | _host->pdata = pdata; |
| 1087 | _host->mmc = mmc; | ||
| 1088 | _host->pdev = pdev; | ||
| 1089 | platform_set_drvdata(pdev, mmc); | 1104 | platform_set_drvdata(pdev, mmc); |
| 1090 | 1105 | ||
| 1091 | _host->set_pwr = pdata->set_pwr; | 1106 | _host->set_pwr = pdata->set_pwr; |
| @@ -1192,12 +1207,9 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
| 1192 | mmc_gpiod_request_cd_irq(mmc); | 1207 | mmc_gpiod_request_cd_irq(mmc); |
| 1193 | } | 1208 | } |
| 1194 | 1209 | ||
| 1195 | *host = _host; | ||
| 1196 | |||
| 1197 | return 0; | 1210 | return 0; |
| 1198 | 1211 | ||
| 1199 | host_free: | 1212 | host_free: |
| 1200 | mmc_free_host(mmc); | ||
| 1201 | 1213 | ||
| 1202 | return ret; | 1214 | return ret; |
| 1203 | } | 1215 | } |
| @@ -1222,7 +1234,6 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) | |||
| 1222 | pm_runtime_disable(&pdev->dev); | 1234 | pm_runtime_disable(&pdev->dev); |
| 1223 | 1235 | ||
| 1224 | iounmap(host->ctl); | 1236 | iounmap(host->ctl); |
| 1225 | mmc_free_host(mmc); | ||
| 1226 | } | 1237 | } |
| 1227 | EXPORT_SYMBOL(tmio_mmc_host_remove); | 1238 | EXPORT_SYMBOL(tmio_mmc_host_remove); |
| 1228 | 1239 | ||
| @@ -1237,8 +1248,8 @@ int tmio_mmc_host_runtime_suspend(struct device *dev) | |||
| 1237 | if (host->clk_cache) | 1248 | if (host->clk_cache) |
| 1238 | tmio_mmc_clk_stop(host); | 1249 | tmio_mmc_clk_stop(host); |
| 1239 | 1250 | ||
| 1240 | if (host->pdata->clk_disable) | 1251 | if (host->clk_disable) |
| 1241 | host->pdata->clk_disable(host->pdev); | 1252 | host->clk_disable(host->pdev); |
| 1242 | 1253 | ||
| 1243 | return 0; | 1254 | return 0; |
| 1244 | } | 1255 | } |
diff --git a/drivers/mmc/host/toshsd.c b/drivers/mmc/host/toshsd.c index 4666262edaca..e2cdd5fb1423 100644 --- a/drivers/mmc/host/toshsd.c +++ b/drivers/mmc/host/toshsd.c | |||
| @@ -176,7 +176,8 @@ static irqreturn_t toshsd_thread_irq(int irq, void *dev_id) | |||
| 176 | spin_lock_irqsave(&host->lock, flags); | 176 | spin_lock_irqsave(&host->lock, flags); |
| 177 | 177 | ||
| 178 | if (!sg_miter_next(sg_miter)) | 178 | if (!sg_miter_next(sg_miter)) |
| 179 | return IRQ_HANDLED; | 179 | goto done; |
| 180 | |||
| 180 | buf = sg_miter->addr; | 181 | buf = sg_miter->addr; |
| 181 | 182 | ||
| 182 | /* Ensure we dont read more than one block. The chip will interrupt us | 183 | /* Ensure we dont read more than one block. The chip will interrupt us |
| @@ -198,6 +199,7 @@ static irqreturn_t toshsd_thread_irq(int irq, void *dev_id) | |||
| 198 | sg_miter->consumed = count; | 199 | sg_miter->consumed = count; |
| 199 | sg_miter_stop(sg_miter); | 200 | sg_miter_stop(sg_miter); |
| 200 | 201 | ||
| 202 | done: | ||
| 201 | spin_unlock_irqrestore(&host->lock, flags); | 203 | spin_unlock_irqrestore(&host->lock, flags); |
| 202 | 204 | ||
| 203 | return IRQ_HANDLED; | 205 | return IRQ_HANDLED; |
| @@ -699,18 +701,7 @@ static struct pci_driver toshsd_driver = { | |||
| 699 | .driver.pm = &toshsd_pm_ops, | 701 | .driver.pm = &toshsd_pm_ops, |
| 700 | }; | 702 | }; |
| 701 | 703 | ||
| 702 | static int __init toshsd_drv_init(void) | 704 | module_pci_driver(toshsd_driver); |
| 703 | { | ||
| 704 | return pci_register_driver(&toshsd_driver); | ||
| 705 | } | ||
| 706 | |||
| 707 | static void __exit toshsd_drv_exit(void) | ||
| 708 | { | ||
| 709 | pci_unregister_driver(&toshsd_driver); | ||
| 710 | } | ||
| 711 | |||
| 712 | module_init(toshsd_drv_init); | ||
| 713 | module_exit(toshsd_drv_exit); | ||
| 714 | 705 | ||
| 715 | MODULE_AUTHOR("Ondrej Zary, Richard Betts"); | 706 | MODULE_AUTHOR("Ondrej Zary, Richard Betts"); |
| 716 | MODULE_DESCRIPTION("Toshiba PCI Secure Digital Host Controller Interface driver"); | 707 | MODULE_DESCRIPTION("Toshiba PCI Secure Digital Host Controller Interface driver"); |
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index 4262296c12fa..fbabbb82b354 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c | |||
| @@ -659,7 +659,7 @@ static void __vub300_irqpoll_response(struct vub300_mmc_host *vub300) | |||
| 659 | static void __do_poll(struct vub300_mmc_host *vub300) | 659 | static void __do_poll(struct vub300_mmc_host *vub300) |
| 660 | { | 660 | { |
| 661 | /* cmd_mutex is held by vub300_pollwork_thread */ | 661 | /* cmd_mutex is held by vub300_pollwork_thread */ |
| 662 | long commretval; | 662 | unsigned long commretval; |
| 663 | mod_timer(&vub300->inactivity_timer, jiffies + HZ); | 663 | mod_timer(&vub300->inactivity_timer, jiffies + HZ); |
| 664 | init_completion(&vub300->irqpoll_complete); | 664 | init_completion(&vub300->irqpoll_complete); |
| 665 | send_irqpoll(vub300); | 665 | send_irqpoll(vub300); |
| @@ -671,8 +671,6 @@ static void __do_poll(struct vub300_mmc_host *vub300) | |||
| 671 | vub300->usb_timed_out = 1; | 671 | vub300->usb_timed_out = 1; |
| 672 | usb_kill_urb(vub300->command_out_urb); | 672 | usb_kill_urb(vub300->command_out_urb); |
| 673 | usb_kill_urb(vub300->command_res_urb); | 673 | usb_kill_urb(vub300->command_res_urb); |
| 674 | } else if (commretval < 0) { | ||
| 675 | vub300_queue_poll_work(vub300, 1); | ||
| 676 | } else { /* commretval > 0 */ | 674 | } else { /* commretval > 0 */ |
| 677 | __vub300_irqpoll_response(vub300); | 675 | __vub300_irqpoll_response(vub300); |
| 678 | } | 676 | } |
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index 57388171610d..605812820e48 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h | |||
| @@ -96,11 +96,6 @@ | |||
| 96 | #define TMIO_MMC_SDIO_STATUS_QUIRK (1 << 8) | 96 | #define TMIO_MMC_SDIO_STATUS_QUIRK (1 << 8) |
| 97 | 97 | ||
| 98 | /* | 98 | /* |
| 99 | * Some controllers have DMA enable/disable register | ||
| 100 | */ | ||
| 101 | #define TMIO_MMC_HAVE_CTL_DMA_REG (1 << 9) | ||
| 102 | |||
| 103 | /* | ||
| 104 | * Some controllers allows to set SDx actual clock | 99 | * Some controllers allows to set SDx actual clock |
| 105 | */ | 100 | */ |
| 106 | #define TMIO_MMC_CLK_ACTUAL (1 << 10) | 101 | #define TMIO_MMC_CLK_ACTUAL (1 << 10) |
| @@ -112,18 +107,6 @@ void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state); | |||
| 112 | 107 | ||
| 113 | struct dma_chan; | 108 | struct dma_chan; |
| 114 | 109 | ||
| 115 | struct tmio_mmc_dma { | ||
| 116 | void *chan_priv_tx; | ||
| 117 | void *chan_priv_rx; | ||
| 118 | int slave_id_tx; | ||
| 119 | int slave_id_rx; | ||
| 120 | int alignment_shift; | ||
| 121 | dma_addr_t dma_rx_offset; | ||
| 122 | bool (*filter)(struct dma_chan *chan, void *arg); | ||
| 123 | }; | ||
| 124 | |||
| 125 | struct tmio_mmc_host; | ||
| 126 | |||
| 127 | /* | 110 | /* |
| 128 | * data for the MMC controller | 111 | * data for the MMC controller |
| 129 | */ | 112 | */ |
| @@ -132,19 +115,12 @@ struct tmio_mmc_data { | |||
| 132 | unsigned long capabilities; | 115 | unsigned long capabilities; |
| 133 | unsigned long capabilities2; | 116 | unsigned long capabilities2; |
| 134 | unsigned long flags; | 117 | unsigned long flags; |
| 135 | unsigned long bus_shift; | ||
| 136 | u32 ocr_mask; /* available voltages */ | 118 | u32 ocr_mask; /* available voltages */ |
| 137 | struct tmio_mmc_dma *dma; | ||
| 138 | struct device *dev; | ||
| 139 | unsigned int cd_gpio; | 119 | unsigned int cd_gpio; |
| 120 | int alignment_shift; | ||
| 121 | dma_addr_t dma_rx_offset; | ||
| 140 | void (*set_pwr)(struct platform_device *host, int state); | 122 | void (*set_pwr)(struct platform_device *host, int state); |
| 141 | void (*set_clk_div)(struct platform_device *host, int state); | 123 | void (*set_clk_div)(struct platform_device *host, int state); |
| 142 | int (*write16_hook)(struct tmio_mmc_host *host, int addr); | ||
| 143 | /* clock management callbacks */ | ||
| 144 | int (*clk_enable)(struct platform_device *pdev, unsigned int *f); | ||
| 145 | void (*clk_disable)(struct platform_device *pdev); | ||
| 146 | int (*multi_io_quirk)(struct mmc_card *card, | ||
| 147 | unsigned int direction, int blk_size); | ||
| 148 | }; | 124 | }; |
| 149 | 125 | ||
| 150 | /* | 126 | /* |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 4d69c00497bd..a6cf4c063e4e 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
| @@ -83,7 +83,7 @@ struct mmc_ext_csd { | |||
| 83 | bool hpi; /* HPI support bit */ | 83 | bool hpi; /* HPI support bit */ |
| 84 | unsigned int hpi_cmd; /* cmd used as HPI */ | 84 | unsigned int hpi_cmd; /* cmd used as HPI */ |
| 85 | bool bkops; /* background support bit */ | 85 | bool bkops; /* background support bit */ |
| 86 | bool bkops_en; /* background enable bit */ | 86 | bool man_bkops_en; /* manual bkops enable bit */ |
| 87 | unsigned int data_sector_size; /* 512 bytes or 4KB */ | 87 | unsigned int data_sector_size; /* 512 bytes or 4KB */ |
| 88 | unsigned int data_tag_unit_size; /* DATA TAG UNIT size */ | 88 | unsigned int data_tag_unit_size; /* DATA TAG UNIT size */ |
| 89 | unsigned int boot_ro_lock; /* ro lock support */ | 89 | unsigned int boot_ro_lock; /* ro lock support */ |
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index cb2b0400d284..160448f920ac 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h | |||
| @@ -182,7 +182,6 @@ extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen); | |||
| 182 | extern int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount, | 182 | extern int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount, |
| 183 | bool is_rel_write); | 183 | bool is_rel_write); |
| 184 | extern int mmc_hw_reset(struct mmc_host *host); | 184 | extern int mmc_hw_reset(struct mmc_host *host); |
| 185 | extern int mmc_hw_reset_check(struct mmc_host *host); | ||
| 186 | extern int mmc_can_reset(struct mmc_card *card); | 185 | extern int mmc_can_reset(struct mmc_card *card); |
| 187 | 186 | ||
| 188 | extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *); | 187 | extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *); |
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 42b724e8d503..471fb3116dbe 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h | |||
| @@ -106,6 +106,11 @@ struct mmc_data; | |||
| 106 | * @cur_slot, @mrq and @state. These must always be updated | 106 | * @cur_slot, @mrq and @state. These must always be updated |
| 107 | * at the same time while holding @lock. | 107 | * at the same time while holding @lock. |
| 108 | * | 108 | * |
| 109 | * @irq_lock is an irq-safe spinlock protecting the INTMASK register | ||
| 110 | * to allow the interrupt handler to modify it directly. Held for only long | ||
| 111 | * enough to read-modify-write INTMASK and no other locks are grabbed when | ||
| 112 | * holding this one. | ||
| 113 | * | ||
| 109 | * The @mrq field of struct dw_mci_slot is also protected by @lock, | 114 | * The @mrq field of struct dw_mci_slot is also protected by @lock, |
| 110 | * and must always be written at the same time as the slot is added to | 115 | * and must always be written at the same time as the slot is added to |
| 111 | * @queue. | 116 | * @queue. |
| @@ -125,6 +130,7 @@ struct mmc_data; | |||
| 125 | */ | 130 | */ |
| 126 | struct dw_mci { | 131 | struct dw_mci { |
| 127 | spinlock_t lock; | 132 | spinlock_t lock; |
| 133 | spinlock_t irq_lock; | ||
| 128 | void __iomem *regs; | 134 | void __iomem *regs; |
| 129 | 135 | ||
| 130 | struct scatterlist *sg; | 136 | struct scatterlist *sg; |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 9f322706f7cb..0c8cbe5d1550 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
| @@ -166,7 +166,6 @@ struct mmc_async_req { | |||
| 166 | * struct mmc_slot - MMC slot functions | 166 | * struct mmc_slot - MMC slot functions |
| 167 | * | 167 | * |
| 168 | * @cd_irq: MMC/SD-card slot hotplug detection IRQ or -EINVAL | 168 | * @cd_irq: MMC/SD-card slot hotplug detection IRQ or -EINVAL |
| 169 | * @lock: protect the @handler_priv pointer | ||
| 170 | * @handler_priv: MMC/SD-card slot context | 169 | * @handler_priv: MMC/SD-card slot context |
| 171 | * | 170 | * |
| 172 | * Some MMC/SD host controllers implement slot-functions like card and | 171 | * Some MMC/SD host controllers implement slot-functions like card and |
| @@ -176,7 +175,6 @@ struct mmc_async_req { | |||
| 176 | */ | 175 | */ |
| 177 | struct mmc_slot { | 176 | struct mmc_slot { |
| 178 | int cd_irq; | 177 | int cd_irq; |
| 179 | struct mutex lock; | ||
| 180 | void *handler_priv; | 178 | void *handler_priv; |
| 181 | }; | 179 | }; |
| 182 | 180 | ||
| @@ -197,6 +195,7 @@ struct mmc_context_info { | |||
| 197 | }; | 195 | }; |
| 198 | 196 | ||
| 199 | struct regulator; | 197 | struct regulator; |
| 198 | struct mmc_pwrseq; | ||
| 200 | 199 | ||
| 201 | struct mmc_supply { | 200 | struct mmc_supply { |
| 202 | struct regulator *vmmc; /* Card power supply */ | 201 | struct regulator *vmmc; /* Card power supply */ |
| @@ -208,6 +207,7 @@ struct mmc_host { | |||
| 208 | struct device class_dev; | 207 | struct device class_dev; |
| 209 | int index; | 208 | int index; |
| 210 | const struct mmc_host_ops *ops; | 209 | const struct mmc_host_ops *ops; |
| 210 | struct mmc_pwrseq *pwrseq; | ||
| 211 | unsigned int f_min; | 211 | unsigned int f_min; |
| 212 | unsigned int f_max; | 212 | unsigned int f_max; |
| 213 | unsigned int f_init; | 213 | unsigned int f_init; |
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 49ad7a943638..124f562118b8 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
| @@ -53,11 +53,6 @@ | |||
| 53 | #define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */ | 53 | #define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */ |
| 54 | #define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */ | 54 | #define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */ |
| 55 | 55 | ||
| 56 | #define MMC_TUNING_BLK_PATTERN_4BIT_SIZE 64 | ||
| 57 | #define MMC_TUNING_BLK_PATTERN_8BIT_SIZE 128 | ||
| 58 | extern const u8 tuning_blk_pattern_4bit[MMC_TUNING_BLK_PATTERN_4BIT_SIZE]; | ||
| 59 | extern const u8 tuning_blk_pattern_8bit[MMC_TUNING_BLK_PATTERN_8BIT_SIZE]; | ||
| 60 | |||
| 61 | /* class 3 */ | 56 | /* class 3 */ |
| 62 | #define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ | 57 | #define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ |
| 63 | 58 | ||
| @@ -433,6 +428,11 @@ struct _mmc_csd { | |||
| 433 | #define EXT_CSD_BKOPS_LEVEL_2 0x2 | 428 | #define EXT_CSD_BKOPS_LEVEL_2 0x2 |
| 434 | 429 | ||
| 435 | /* | 430 | /* |
| 431 | * BKOPS modes | ||
| 432 | */ | ||
| 433 | #define EXT_CSD_MANUAL_BKOPS_MASK 0x01 | ||
| 434 | |||
| 435 | /* | ||
| 436 | * MMC_SWITCH access modes | 436 | * MMC_SWITCH access modes |
| 437 | */ | 437 | */ |
| 438 | 438 | ||
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index f767a0de611f..c3e3db196738 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h | |||
| @@ -17,6 +17,11 @@ | |||
| 17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 18 | #include <linux/mmc/host.h> | 18 | #include <linux/mmc/host.h> |
| 19 | 19 | ||
| 20 | struct sdhci_host_next { | ||
| 21 | unsigned int sg_count; | ||
| 22 | s32 cookie; | ||
| 23 | }; | ||
| 24 | |||
| 20 | struct sdhci_host { | 25 | struct sdhci_host { |
| 21 | /* Data set by hardware interface driver */ | 26 | /* Data set by hardware interface driver */ |
| 22 | const char *hw_name; /* Hardware bus name */ | 27 | const char *hw_name; /* Hardware bus name */ |
| @@ -106,6 +111,10 @@ struct sdhci_host { | |||
| 106 | #define SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1<<10) | 111 | #define SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1<<10) |
| 107 | /* Capability register bit-63 indicates HS400 support */ | 112 | /* Capability register bit-63 indicates HS400 support */ |
| 108 | #define SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 (1<<11) | 113 | #define SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 (1<<11) |
| 114 | /* forced tuned clock */ | ||
| 115 | #define SDHCI_QUIRK2_TUNING_WORK_AROUND (1<<12) | ||
| 116 | /* disable the block count for single block transactions */ | ||
| 117 | #define SDHCI_QUIRK2_SUPPORT_SINGLE (1<<13) | ||
| 109 | 118 | ||
| 110 | int irq; /* Device IRQ */ | 119 | int irq; /* Device IRQ */ |
| 111 | void __iomem *ioaddr; /* Mapped address */ | 120 | void __iomem *ioaddr; /* Mapped address */ |
| @@ -203,6 +212,7 @@ struct sdhci_host { | |||
| 203 | #define SDHCI_TUNING_MODE_1 0 | 212 | #define SDHCI_TUNING_MODE_1 0 |
| 204 | struct timer_list tuning_timer; /* Timer for tuning */ | 213 | struct timer_list tuning_timer; /* Timer for tuning */ |
| 205 | 214 | ||
| 215 | struct sdhci_host_next next_data; | ||
| 206 | unsigned long private[0] ____cacheline_aligned; | 216 | unsigned long private[0] ____cacheline_aligned; |
| 207 | }; | 217 | }; |
| 208 | #endif /* LINUX_MMC_SDHCI_H */ | 218 | #endif /* LINUX_MMC_SDHCI_H */ |
diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h index 68927ae50845..da77e5e2041d 100644 --- a/include/linux/mmc/sh_mobile_sdhi.h +++ b/include/linux/mmc/sh_mobile_sdhi.h | |||
| @@ -3,20 +3,10 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
| 5 | 5 | ||
| 6 | struct platform_device; | ||
| 7 | |||
| 8 | #define SH_MOBILE_SDHI_IRQ_CARD_DETECT "card_detect" | 6 | #define SH_MOBILE_SDHI_IRQ_CARD_DETECT "card_detect" |
| 9 | #define SH_MOBILE_SDHI_IRQ_SDCARD "sdcard" | 7 | #define SH_MOBILE_SDHI_IRQ_SDCARD "sdcard" |
| 10 | #define SH_MOBILE_SDHI_IRQ_SDIO "sdio" | 8 | #define SH_MOBILE_SDHI_IRQ_SDIO "sdio" |
| 11 | 9 | ||
| 12 | /** | ||
| 13 | * struct sh_mobile_sdhi_ops - SDHI driver callbacks | ||
| 14 | * @cd_wakeup: trigger a card-detection run | ||
| 15 | */ | ||
| 16 | struct sh_mobile_sdhi_ops { | ||
| 17 | void (*cd_wakeup)(const struct platform_device *pdev); | ||
| 18 | }; | ||
| 19 | |||
| 20 | struct sh_mobile_sdhi_info { | 10 | struct sh_mobile_sdhi_info { |
| 21 | int dma_slave_tx; | 11 | int dma_slave_tx; |
| 22 | int dma_slave_rx; | 12 | int dma_slave_rx; |
| @@ -25,11 +15,6 @@ struct sh_mobile_sdhi_info { | |||
| 25 | unsigned long tmio_caps2; | 15 | unsigned long tmio_caps2; |
| 26 | u32 tmio_ocr_mask; /* available MMC voltages */ | 16 | u32 tmio_ocr_mask; /* available MMC voltages */ |
| 27 | unsigned int cd_gpio; | 17 | unsigned int cd_gpio; |
| 28 | |||
| 29 | /* callbacks for board specific setup code */ | ||
| 30 | int (*init)(struct platform_device *pdev, | ||
| 31 | const struct sh_mobile_sdhi_ops *ops); | ||
| 32 | void (*cleanup)(struct platform_device *pdev); | ||
| 33 | }; | 18 | }; |
| 34 | 19 | ||
| 35 | #endif /* LINUX_MMC_SH_MOBILE_SDHI_H */ | 20 | #endif /* LINUX_MMC_SH_MOBILE_SDHI_H */ |
diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h index e56fa24c9322..3945a8c9d3cb 100644 --- a/include/linux/mmc/slot-gpio.h +++ b/include/linux/mmc/slot-gpio.h | |||
| @@ -15,12 +15,10 @@ struct mmc_host; | |||
| 15 | 15 | ||
| 16 | int mmc_gpio_get_ro(struct mmc_host *host); | 16 | int mmc_gpio_get_ro(struct mmc_host *host); |
| 17 | int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio); | 17 | int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio); |
| 18 | void mmc_gpio_free_ro(struct mmc_host *host); | ||
| 19 | 18 | ||
| 20 | int mmc_gpio_get_cd(struct mmc_host *host); | 19 | int mmc_gpio_get_cd(struct mmc_host *host); |
| 21 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, | 20 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio, |
| 22 | unsigned int debounce); | 21 | unsigned int debounce); |
| 23 | void mmc_gpio_free_cd(struct mmc_host *host); | ||
| 24 | 22 | ||
| 25 | int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, | 23 | int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, |
| 26 | unsigned int idx, bool override_active_level, | 24 | unsigned int idx, bool override_active_level, |
| @@ -28,7 +26,8 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, | |||
| 28 | int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, | 26 | int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, |
| 29 | unsigned int idx, bool override_active_level, | 27 | unsigned int idx, bool override_active_level, |
| 30 | unsigned int debounce, bool *gpio_invert); | 28 | unsigned int debounce, bool *gpio_invert); |
| 31 | void mmc_gpiod_free_cd(struct mmc_host *host); | 29 | void mmc_gpio_set_cd_isr(struct mmc_host *host, |
| 30 | irqreturn_t (*isr)(int irq, void *dev_id)); | ||
| 32 | void mmc_gpiod_request_cd_irq(struct mmc_host *host); | 31 | void mmc_gpiod_request_cd_irq(struct mmc_host *host); |
| 33 | 32 | ||
| 34 | #endif | 33 | #endif |
diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h index 5c188f4e9bec..929469291406 100644 --- a/include/linux/platform_data/mmc-omap.h +++ b/include/linux/platform_data/mmc-omap.h | |||
| @@ -31,10 +31,6 @@ struct omap_mmc_platform_data { | |||
| 31 | void (*cleanup)(struct device *dev); | 31 | void (*cleanup)(struct device *dev); |
| 32 | void (*shutdown)(struct device *dev); | 32 | void (*shutdown)(struct device *dev); |
| 33 | 33 | ||
| 34 | /* To handle board related suspend/resume functionality for MMC */ | ||
| 35 | int (*suspend)(struct device *dev, int slot); | ||
| 36 | int (*resume)(struct device *dev, int slot); | ||
| 37 | |||
| 38 | /* Return context loss count due to PM states changing */ | 34 | /* Return context loss count due to PM states changing */ |
| 39 | int (*get_context_loss_count)(struct device *dev); | 35 | int (*get_context_loss_count)(struct device *dev); |
| 40 | 36 | ||
