diff options
73 files changed, 1807 insertions, 790 deletions
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt index 85aada2263d5..458b57f199af 100644 --- a/Documentation/devicetree/bindings/mmc/mmc.txt +++ b/Documentation/devicetree/bindings/mmc/mmc.txt | |||
| @@ -28,6 +28,7 @@ Optional properties: | |||
| 28 | - cap-mmc-highspeed: MMC high-speed timing is supported | 28 | - cap-mmc-highspeed: MMC high-speed timing is supported |
| 29 | - cap-power-off-card: powering off the card is safe | 29 | - cap-power-off-card: powering off the card is safe |
| 30 | - cap-sdio-irq: enable SDIO IRQ signalling on this interface | 30 | - cap-sdio-irq: enable SDIO IRQ signalling on this interface |
| 31 | - full-pwr-cycle: full power cycle of the card is supported | ||
| 31 | 32 | ||
| 32 | *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line | 33 | *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line |
| 33 | polarity properties, we have to fix the meaning of the "normal" and "inverted" | 34 | polarity properties, we have to fix the meaning of the "normal" and "inverted" |
diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt new file mode 100644 index 000000000000..8a3d91d47b6a --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | * Rockchip specific extensions to the Synopsis Designware Mobile | ||
| 2 | Storage Host Controller | ||
| 3 | |||
| 4 | The Synopsis designware mobile storage host controller is used to interface | ||
| 5 | a SoC with storage medium such as eMMC or SD/MMC cards. This file documents | ||
| 6 | differences between the core Synopsis dw mshc controller properties described | ||
| 7 | by synopsis-dw-mshc.txt and the properties used by the Rockchip specific | ||
| 8 | extensions to the Synopsis Designware Mobile Storage Host Controller. | ||
| 9 | |||
| 10 | Required Properties: | ||
| 11 | |||
| 12 | * compatible: should be | ||
| 13 | - "rockchip,rk2928-dw-mshc": for Rockchip RK2928 and following | ||
| 14 | |||
| 15 | Example: | ||
| 16 | |||
| 17 | rkdwmmc0@12200000 { | ||
| 18 | compatible = "rockchip,rk2928-dw-mshc"; | ||
| 19 | reg = <0x12200000 0x1000>; | ||
| 20 | interrupts = <0 75 0>; | ||
| 21 | #address-cells = <1>; | ||
| 22 | #size-cells = <0>; | ||
| 23 | }; | ||
diff --git a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt index 1180d7814af8..cdcebea9c6f5 100644 --- a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt | |||
| @@ -39,6 +39,19 @@ Required Properties: | |||
| 39 | 39 | ||
| 40 | Optional properties: | 40 | Optional properties: |
| 41 | 41 | ||
| 42 | * clocks: from common clock binding: handle to biu and ciu clocks for the | ||
| 43 | bus interface unit clock and the card interface unit clock. | ||
| 44 | |||
| 45 | * clock-names: from common clock binding: Shall be "biu" and "ciu". | ||
| 46 | If the biu clock is missing we'll simply skip enabling it. If the | ||
| 47 | ciu clock is missing we'll just assume that the clock is running at | ||
| 48 | clock-frequency. It is an error to omit both the ciu clock and the | ||
| 49 | clock-frequency. | ||
| 50 | |||
| 51 | * clock-frequency: should be the frequency (in Hz) of the ciu clock. If this | ||
| 52 | is specified and the ciu clock is specified then we'll try to set the ciu | ||
| 53 | clock to this at probe time. | ||
| 54 | |||
| 42 | * num-slots: specifies the number of slots supported by the controller. | 55 | * num-slots: specifies the number of slots supported by the controller. |
| 43 | The number of physical slots actually used could be equal or less than the | 56 | The number of physical slots actually used could be equal or less than the |
| 44 | value specified by num-slots. If this property is not specified, the value | 57 | value specified by num-slots. If this property is not specified, the value |
| @@ -55,6 +68,9 @@ Optional properties: | |||
| 55 | 68 | ||
| 56 | * broken-cd: as documented in mmc core bindings. | 69 | * broken-cd: as documented in mmc core bindings. |
| 57 | 70 | ||
| 71 | * vmmc-supply: The phandle to the regulator to use for vmmc. If this is | ||
| 72 | specified we'll defer probe until we can find this regulator. | ||
| 73 | |||
| 58 | Aliases: | 74 | Aliases: |
| 59 | 75 | ||
| 60 | - All the MSHC controller nodes should be represented in the aliases node using | 76 | - All the MSHC controller nodes should be represented in the aliases node using |
| @@ -67,6 +83,8 @@ board specific portions as listed below. | |||
| 67 | 83 | ||
| 68 | dwmmc0@12200000 { | 84 | dwmmc0@12200000 { |
| 69 | compatible = "snps,dw-mshc"; | 85 | compatible = "snps,dw-mshc"; |
| 86 | clocks = <&clock 351>, <&clock 132>; | ||
| 87 | clock-names = "biu", "ciu"; | ||
| 70 | reg = <0x12200000 0x1000>; | 88 | reg = <0x12200000 0x1000>; |
| 71 | interrupts = <0 75 0>; | 89 | interrupts = <0 75 0>; |
| 72 | #address-cells = <1>; | 90 | #address-cells = <1>; |
| @@ -74,11 +92,13 @@ board specific portions as listed below. | |||
| 74 | }; | 92 | }; |
| 75 | 93 | ||
| 76 | dwmmc0@12200000 { | 94 | dwmmc0@12200000 { |
| 95 | clock-frequency = <400000000>; | ||
| 77 | num-slots = <1>; | 96 | num-slots = <1>; |
| 78 | supports-highspeed; | 97 | supports-highspeed; |
| 79 | broken-cd; | 98 | broken-cd; |
| 80 | fifo-depth = <0x80>; | 99 | fifo-depth = <0x80>; |
| 81 | card-detect-delay = <200>; | 100 | card-detect-delay = <200>; |
| 101 | vmmc-supply = <&buck8>; | ||
| 82 | 102 | ||
| 83 | slot@0 { | 103 | slot@0 { |
| 84 | reg = <0>; | 104 | reg = <0>; |
diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig index e3bf2d65618e..65edf6d47215 100644 --- a/arch/arm/configs/bcm_defconfig +++ b/arch/arm/configs/bcm_defconfig | |||
| @@ -78,6 +78,13 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y | |||
| 78 | CONFIG_LCD_CLASS_DEVICE=y | 78 | CONFIG_LCD_CLASS_DEVICE=y |
| 79 | CONFIG_BACKLIGHT_CLASS_DEVICE=y | 79 | CONFIG_BACKLIGHT_CLASS_DEVICE=y |
| 80 | # CONFIG_USB_SUPPORT is not set | 80 | # CONFIG_USB_SUPPORT is not set |
| 81 | CONFIG_MMC=y | ||
| 82 | CONFIG_MMC_UNSAFE_RESUME=y | ||
| 83 | CONFIG_MMC_BLOCK_MINORS=32 | ||
| 84 | CONFIG_MMC_TEST=y | ||
| 85 | CONFIG_MMC_SDHCI=y | ||
| 86 | CONFIG_MMC_SDHCI_PLTFM=y | ||
| 87 | CONFIG_MMC_SDHCI_BCM_KONA=y | ||
| 81 | CONFIG_NEW_LEDS=y | 88 | CONFIG_NEW_LEDS=y |
| 82 | CONFIG_LEDS_CLASS=y | 89 | CONFIG_LEDS_CLASS=y |
| 83 | CONFIG_LEDS_TRIGGERS=y | 90 | CONFIG_LEDS_TRIGGERS=y |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index dd27b0783d52..cd0b7f4a1ff2 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
| 35 | #include <linux/capability.h> | 35 | #include <linux/capability.h> |
| 36 | #include <linux/compat.h> | 36 | #include <linux/compat.h> |
| 37 | #include <linux/pm_runtime.h> | ||
| 37 | 38 | ||
| 38 | #include <linux/mmc/ioctl.h> | 39 | #include <linux/mmc/ioctl.h> |
| 39 | #include <linux/mmc/card.h> | 40 | #include <linux/mmc/card.h> |
| @@ -58,6 +59,8 @@ MODULE_ALIAS("mmc:block"); | |||
| 58 | #define INAND_CMD38_ARG_SECTRIM1 0x81 | 59 | #define INAND_CMD38_ARG_SECTRIM1 0x81 |
| 59 | #define INAND_CMD38_ARG_SECTRIM2 0x88 | 60 | #define INAND_CMD38_ARG_SECTRIM2 0x88 |
| 60 | #define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ | 61 | #define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ |
| 62 | #define MMC_SANITIZE_REQ_TIMEOUT 240000 | ||
| 63 | #define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16) | ||
| 61 | 64 | ||
| 62 | #define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \ | 65 | #define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \ |
| 63 | (req->cmd_flags & REQ_META)) && \ | 66 | (req->cmd_flags & REQ_META)) && \ |
| @@ -222,7 +225,7 @@ static ssize_t power_ro_lock_store(struct device *dev, | |||
| 222 | md = mmc_blk_get(dev_to_disk(dev)); | 225 | md = mmc_blk_get(dev_to_disk(dev)); |
| 223 | card = md->queue.card; | 226 | card = md->queue.card; |
| 224 | 227 | ||
| 225 | mmc_claim_host(card->host); | 228 | mmc_get_card(card); |
| 226 | 229 | ||
| 227 | ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, | 230 | ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, |
| 228 | card->ext_csd.boot_ro_lock | | 231 | card->ext_csd.boot_ro_lock | |
| @@ -233,7 +236,7 @@ static ssize_t power_ro_lock_store(struct device *dev, | |||
| 233 | else | 236 | else |
| 234 | card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN; | 237 | card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN; |
| 235 | 238 | ||
| 236 | mmc_release_host(card->host); | 239 | mmc_put_card(card); |
| 237 | 240 | ||
| 238 | if (!ret) { | 241 | if (!ret) { |
| 239 | pr_info("%s: Locking boot partition ro until next power on\n", | 242 | pr_info("%s: Locking boot partition ro until next power on\n", |
| @@ -408,6 +411,35 @@ static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status, | |||
| 408 | return err; | 411 | return err; |
| 409 | } | 412 | } |
| 410 | 413 | ||
| 414 | static int ioctl_do_sanitize(struct mmc_card *card) | ||
| 415 | { | ||
| 416 | int err; | ||
| 417 | |||
| 418 | if (!(mmc_can_sanitize(card) && | ||
| 419 | (card->host->caps2 & MMC_CAP2_SANITIZE))) { | ||
| 420 | pr_warn("%s: %s - SANITIZE is not supported\n", | ||
| 421 | mmc_hostname(card->host), __func__); | ||
| 422 | err = -EOPNOTSUPP; | ||
| 423 | goto out; | ||
| 424 | } | ||
| 425 | |||
| 426 | pr_debug("%s: %s - SANITIZE IN PROGRESS...\n", | ||
| 427 | mmc_hostname(card->host), __func__); | ||
| 428 | |||
| 429 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
| 430 | EXT_CSD_SANITIZE_START, 1, | ||
| 431 | MMC_SANITIZE_REQ_TIMEOUT); | ||
| 432 | |||
| 433 | if (err) | ||
| 434 | pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n", | ||
| 435 | mmc_hostname(card->host), __func__, err); | ||
| 436 | |||
| 437 | pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host), | ||
| 438 | __func__); | ||
| 439 | out: | ||
| 440 | return err; | ||
| 441 | } | ||
| 442 | |||
| 411 | static int mmc_blk_ioctl_cmd(struct block_device *bdev, | 443 | static int mmc_blk_ioctl_cmd(struct block_device *bdev, |
| 412 | struct mmc_ioc_cmd __user *ic_ptr) | 444 | struct mmc_ioc_cmd __user *ic_ptr) |
| 413 | { | 445 | { |
| @@ -491,7 +523,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, | |||
| 491 | 523 | ||
| 492 | mrq.cmd = &cmd; | 524 | mrq.cmd = &cmd; |
| 493 | 525 | ||
| 494 | mmc_claim_host(card->host); | 526 | mmc_get_card(card); |
| 495 | 527 | ||
| 496 | err = mmc_blk_part_switch(card, md); | 528 | err = mmc_blk_part_switch(card, md); |
| 497 | if (err) | 529 | if (err) |
| @@ -510,6 +542,17 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, | |||
| 510 | goto cmd_rel_host; | 542 | goto cmd_rel_host; |
| 511 | } | 543 | } |
| 512 | 544 | ||
| 545 | if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) && | ||
| 546 | (cmd.opcode == MMC_SWITCH)) { | ||
| 547 | err = ioctl_do_sanitize(card); | ||
| 548 | |||
| 549 | if (err) | ||
| 550 | pr_err("%s: ioctl_do_sanitize() failed. err = %d", | ||
| 551 | __func__, err); | ||
| 552 | |||
| 553 | goto cmd_rel_host; | ||
| 554 | } | ||
| 555 | |||
| 513 | mmc_wait_for_req(card->host, &mrq); | 556 | mmc_wait_for_req(card->host, &mrq); |
| 514 | 557 | ||
| 515 | if (cmd.error) { | 558 | if (cmd.error) { |
| @@ -558,7 +601,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, | |||
| 558 | } | 601 | } |
| 559 | 602 | ||
| 560 | cmd_rel_host: | 603 | cmd_rel_host: |
| 561 | mmc_release_host(card->host); | 604 | mmc_put_card(card); |
| 562 | 605 | ||
| 563 | cmd_done: | 606 | cmd_done: |
| 564 | mmc_blk_put(md); | 607 | mmc_blk_put(md); |
| @@ -939,10 +982,10 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, | |||
| 939 | { | 982 | { |
| 940 | struct mmc_blk_data *md = mq->data; | 983 | struct mmc_blk_data *md = mq->data; |
| 941 | struct mmc_card *card = md->queue.card; | 984 | struct mmc_card *card = md->queue.card; |
| 942 | unsigned int from, nr, arg, trim_arg, erase_arg; | 985 | unsigned int from, nr, arg; |
| 943 | int err = 0, type = MMC_BLK_SECDISCARD; | 986 | int err = 0, type = MMC_BLK_SECDISCARD; |
| 944 | 987 | ||
| 945 | if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) { | 988 | if (!(mmc_can_secure_erase_trim(card))) { |
| 946 | err = -EOPNOTSUPP; | 989 | err = -EOPNOTSUPP; |
| 947 | goto out; | 990 | goto out; |
| 948 | } | 991 | } |
| @@ -950,23 +993,11 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, | |||
| 950 | from = blk_rq_pos(req); | 993 | from = blk_rq_pos(req); |
| 951 | nr = blk_rq_sectors(req); | 994 | nr = blk_rq_sectors(req); |
| 952 | 995 | ||
| 953 | /* The sanitize operation is supported at v4.5 only */ | 996 | if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) |
| 954 | if (mmc_can_sanitize(card)) { | 997 | arg = MMC_SECURE_TRIM1_ARG; |
| 955 | erase_arg = MMC_ERASE_ARG; | 998 | else |
| 956 | trim_arg = MMC_TRIM_ARG; | 999 | arg = MMC_SECURE_ERASE_ARG; |
| 957 | } else { | ||
| 958 | erase_arg = MMC_SECURE_ERASE_ARG; | ||
| 959 | trim_arg = MMC_SECURE_TRIM1_ARG; | ||
| 960 | } | ||
| 961 | 1000 | ||
| 962 | if (mmc_erase_group_aligned(card, from, nr)) | ||
| 963 | arg = erase_arg; | ||
| 964 | else if (mmc_can_trim(card)) | ||
| 965 | arg = trim_arg; | ||
| 966 | else { | ||
| 967 | err = -EINVAL; | ||
| 968 | goto out; | ||
| 969 | } | ||
| 970 | retry: | 1001 | retry: |
| 971 | if (card->quirks & MMC_QUIRK_INAND_CMD38) { | 1002 | if (card->quirks & MMC_QUIRK_INAND_CMD38) { |
| 972 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1003 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| @@ -1002,9 +1033,6 @@ retry: | |||
| 1002 | goto out; | 1033 | goto out; |
| 1003 | } | 1034 | } |
| 1004 | 1035 | ||
| 1005 | if (mmc_can_sanitize(card)) | ||
| 1006 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
| 1007 | EXT_CSD_SANITIZE_START, 1, 0); | ||
| 1008 | out_retry: | 1036 | out_retry: |
| 1009 | if (err && !mmc_blk_reset(md, card->host, type)) | 1037 | if (err && !mmc_blk_reset(md, card->host, type)) |
| 1010 | goto retry; | 1038 | goto retry; |
| @@ -1895,7 +1923,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 1895 | 1923 | ||
| 1896 | if (req && !mq->mqrq_prev->req) | 1924 | if (req && !mq->mqrq_prev->req) |
| 1897 | /* claim host only for the first request */ | 1925 | /* claim host only for the first request */ |
| 1898 | mmc_claim_host(card->host); | 1926 | mmc_get_card(card); |
| 1899 | 1927 | ||
| 1900 | ret = mmc_blk_part_switch(card, md); | 1928 | ret = mmc_blk_part_switch(card, md); |
| 1901 | if (ret) { | 1929 | if (ret) { |
| @@ -1939,7 +1967,7 @@ out: | |||
| 1939 | * In case sepecial request, there is no reentry to | 1967 | * In case sepecial request, there is no reentry to |
| 1940 | * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'. | 1968 | * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'. |
| 1941 | */ | 1969 | */ |
| 1942 | mmc_release_host(card->host); | 1970 | mmc_put_card(card); |
| 1943 | return ret; | 1971 | return ret; |
| 1944 | } | 1972 | } |
| 1945 | 1973 | ||
| @@ -2158,6 +2186,14 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md) | |||
| 2158 | struct mmc_card *card; | 2186 | struct mmc_card *card; |
| 2159 | 2187 | ||
| 2160 | if (md) { | 2188 | if (md) { |
| 2189 | /* | ||
| 2190 | * Flush remaining requests and free queues. It | ||
| 2191 | * is freeing the queue that stops new requests | ||
| 2192 | * from being accepted. | ||
| 2193 | */ | ||
| 2194 | mmc_cleanup_queue(&md->queue); | ||
| 2195 | if (md->flags & MMC_BLK_PACKED_CMD) | ||
| 2196 | mmc_packed_clean(&md->queue); | ||
| 2161 | card = md->queue.card; | 2197 | card = md->queue.card; |
| 2162 | if (md->disk->flags & GENHD_FL_UP) { | 2198 | if (md->disk->flags & GENHD_FL_UP) { |
| 2163 | device_remove_file(disk_to_dev(md->disk), &md->force_ro); | 2199 | device_remove_file(disk_to_dev(md->disk), &md->force_ro); |
| @@ -2166,14 +2202,8 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md) | |||
| 2166 | device_remove_file(disk_to_dev(md->disk), | 2202 | device_remove_file(disk_to_dev(md->disk), |
| 2167 | &md->power_ro_lock); | 2203 | &md->power_ro_lock); |
| 2168 | 2204 | ||
| 2169 | /* Stop new requests from getting into the queue */ | ||
| 2170 | del_gendisk(md->disk); | 2205 | del_gendisk(md->disk); |
| 2171 | } | 2206 | } |
| 2172 | |||
| 2173 | /* Then flush out any already in there */ | ||
| 2174 | mmc_cleanup_queue(&md->queue); | ||
| 2175 | if (md->flags & MMC_BLK_PACKED_CMD) | ||
| 2176 | mmc_packed_clean(&md->queue); | ||
| 2177 | mmc_blk_put(md); | 2207 | mmc_blk_put(md); |
| 2178 | } | 2208 | } |
| 2179 | } | 2209 | } |
| @@ -2336,6 +2366,19 @@ static int mmc_blk_probe(struct mmc_card *card) | |||
| 2336 | if (mmc_add_disk(part_md)) | 2366 | if (mmc_add_disk(part_md)) |
| 2337 | goto out; | 2367 | goto out; |
| 2338 | } | 2368 | } |
| 2369 | |||
| 2370 | pm_runtime_set_autosuspend_delay(&card->dev, 3000); | ||
| 2371 | pm_runtime_use_autosuspend(&card->dev); | ||
| 2372 | |||
| 2373 | /* | ||
| 2374 | * Don't enable runtime PM for SD-combo cards here. Leave that | ||
| 2375 | * decision to be taken during the SDIO init sequence instead. | ||
| 2376 | */ | ||
| 2377 | if (card->type != MMC_TYPE_SD_COMBO) { | ||
| 2378 | pm_runtime_set_active(&card->dev); | ||
| 2379 | pm_runtime_enable(&card->dev); | ||
| 2380 | } | ||
| 2381 | |||
| 2339 | return 0; | 2382 | return 0; |
| 2340 | 2383 | ||
| 2341 | out: | 2384 | out: |
| @@ -2349,20 +2392,24 @@ static void mmc_blk_remove(struct mmc_card *card) | |||
| 2349 | struct mmc_blk_data *md = mmc_get_drvdata(card); | 2392 | struct mmc_blk_data *md = mmc_get_drvdata(card); |
| 2350 | 2393 | ||
| 2351 | mmc_blk_remove_parts(card, md); | 2394 | mmc_blk_remove_parts(card, md); |
| 2395 | pm_runtime_get_sync(&card->dev); | ||
| 2352 | mmc_claim_host(card->host); | 2396 | mmc_claim_host(card->host); |
| 2353 | mmc_blk_part_switch(card, md); | 2397 | mmc_blk_part_switch(card, md); |
| 2354 | mmc_release_host(card->host); | 2398 | mmc_release_host(card->host); |
| 2399 | if (card->type != MMC_TYPE_SD_COMBO) | ||
| 2400 | pm_runtime_disable(&card->dev); | ||
| 2401 | pm_runtime_put_noidle(&card->dev); | ||
| 2355 | mmc_blk_remove_req(md); | 2402 | mmc_blk_remove_req(md); |
| 2356 | mmc_set_drvdata(card, NULL); | 2403 | mmc_set_drvdata(card, NULL); |
| 2357 | } | 2404 | } |
| 2358 | 2405 | ||
| 2359 | #ifdef CONFIG_PM | 2406 | static int _mmc_blk_suspend(struct mmc_card *card) |
| 2360 | static int mmc_blk_suspend(struct mmc_card *card) | ||
| 2361 | { | 2407 | { |
| 2362 | struct mmc_blk_data *part_md; | 2408 | struct mmc_blk_data *part_md; |
| 2363 | struct mmc_blk_data *md = mmc_get_drvdata(card); | 2409 | struct mmc_blk_data *md = mmc_get_drvdata(card); |
| 2364 | 2410 | ||
| 2365 | if (md) { | 2411 | if (md) { |
| 2412 | pm_runtime_get_sync(&card->dev); | ||
| 2366 | mmc_queue_suspend(&md->queue); | 2413 | mmc_queue_suspend(&md->queue); |
| 2367 | list_for_each_entry(part_md, &md->part, part) { | 2414 | list_for_each_entry(part_md, &md->part, part) { |
| 2368 | mmc_queue_suspend(&part_md->queue); | 2415 | mmc_queue_suspend(&part_md->queue); |
| @@ -2371,6 +2418,17 @@ static int mmc_blk_suspend(struct mmc_card *card) | |||
| 2371 | return 0; | 2418 | return 0; |
| 2372 | } | 2419 | } |
| 2373 | 2420 | ||
| 2421 | static void mmc_blk_shutdown(struct mmc_card *card) | ||
| 2422 | { | ||
| 2423 | _mmc_blk_suspend(card); | ||
| 2424 | } | ||
| 2425 | |||
| 2426 | #ifdef CONFIG_PM | ||
| 2427 | static int mmc_blk_suspend(struct mmc_card *card) | ||
| 2428 | { | ||
| 2429 | return _mmc_blk_suspend(card); | ||
| 2430 | } | ||
| 2431 | |||
| 2374 | static int mmc_blk_resume(struct mmc_card *card) | 2432 | static int mmc_blk_resume(struct mmc_card *card) |
| 2375 | { | 2433 | { |
| 2376 | struct mmc_blk_data *part_md; | 2434 | struct mmc_blk_data *part_md; |
| @@ -2386,6 +2444,7 @@ static int mmc_blk_resume(struct mmc_card *card) | |||
| 2386 | list_for_each_entry(part_md, &md->part, part) { | 2444 | list_for_each_entry(part_md, &md->part, part) { |
| 2387 | mmc_queue_resume(&part_md->queue); | 2445 | mmc_queue_resume(&part_md->queue); |
| 2388 | } | 2446 | } |
| 2447 | pm_runtime_put(&card->dev); | ||
| 2389 | } | 2448 | } |
| 2390 | return 0; | 2449 | return 0; |
| 2391 | } | 2450 | } |
| @@ -2402,6 +2461,7 @@ static struct mmc_driver mmc_driver = { | |||
| 2402 | .remove = mmc_blk_remove, | 2461 | .remove = mmc_blk_remove, |
| 2403 | .suspend = mmc_blk_suspend, | 2462 | .suspend = mmc_blk_suspend, |
| 2404 | .resume = mmc_blk_resume, | 2463 | .resume = mmc_blk_resume, |
| 2464 | .shutdown = mmc_blk_shutdown, | ||
| 2405 | }; | 2465 | }; |
| 2406 | 2466 | ||
| 2407 | static int __init mmc_blk_init(void) | 2467 | static int __init mmc_blk_init(void) |
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 759714ed6bee..a69df5216274 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c | |||
| @@ -3025,12 +3025,17 @@ static void mmc_test_remove(struct mmc_card *card) | |||
| 3025 | mmc_test_free_dbgfs_file(card); | 3025 | mmc_test_free_dbgfs_file(card); |
| 3026 | } | 3026 | } |
| 3027 | 3027 | ||
| 3028 | static void mmc_test_shutdown(struct mmc_card *card) | ||
| 3029 | { | ||
| 3030 | } | ||
| 3031 | |||
| 3028 | static struct mmc_driver mmc_driver = { | 3032 | static struct mmc_driver mmc_driver = { |
| 3029 | .drv = { | 3033 | .drv = { |
| 3030 | .name = "mmc_test", | 3034 | .name = "mmc_test", |
| 3031 | }, | 3035 | }, |
| 3032 | .probe = mmc_test_probe, | 3036 | .probe = mmc_test_probe, |
| 3033 | .remove = mmc_test_remove, | 3037 | .remove = mmc_test_remove, |
| 3038 | .shutdown = mmc_test_shutdown, | ||
| 3034 | }; | 3039 | }; |
| 3035 | 3040 | ||
| 3036 | static int __init mmc_test_init(void) | 3041 | static int __init mmc_test_init(void) |
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 9447a0e970d1..fa9632eb63f1 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c | |||
| @@ -173,7 +173,7 @@ static void mmc_queue_setup_discard(struct request_queue *q, | |||
| 173 | /* granularity must not be greater than max. discard */ | 173 | /* granularity must not be greater than max. discard */ |
| 174 | if (card->pref_erase > max_discard) | 174 | if (card->pref_erase > max_discard) |
| 175 | q->limits.discard_granularity = 0; | 175 | q->limits.discard_granularity = 0; |
| 176 | if (mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card)) | 176 | if (mmc_can_secure_erase_trim(card)) |
| 177 | queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q); | 177 | queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q); |
| 178 | } | 178 | } |
| 179 | 179 | ||
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 9d5c71125576..704bf66f5873 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
| @@ -122,15 +122,39 @@ static int mmc_bus_remove(struct device *dev) | |||
| 122 | return 0; | 122 | return 0; |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | static void mmc_bus_shutdown(struct device *dev) | ||
| 126 | { | ||
| 127 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | ||
| 128 | struct mmc_card *card = mmc_dev_to_card(dev); | ||
| 129 | struct mmc_host *host = card->host; | ||
| 130 | int ret; | ||
| 131 | |||
| 132 | if (dev->driver && drv->shutdown) | ||
| 133 | drv->shutdown(card); | ||
| 134 | |||
| 135 | if (host->bus_ops->shutdown) { | ||
| 136 | ret = host->bus_ops->shutdown(host); | ||
| 137 | if (ret) | ||
| 138 | pr_warn("%s: error %d during shutdown\n", | ||
| 139 | mmc_hostname(host), ret); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 125 | #ifdef CONFIG_PM_SLEEP | 143 | #ifdef CONFIG_PM_SLEEP |
| 126 | static int mmc_bus_suspend(struct device *dev) | 144 | static int mmc_bus_suspend(struct device *dev) |
| 127 | { | 145 | { |
| 128 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 146 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
| 129 | struct mmc_card *card = mmc_dev_to_card(dev); | 147 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 130 | int ret = 0; | 148 | struct mmc_host *host = card->host; |
| 149 | int ret; | ||
| 131 | 150 | ||
| 132 | if (dev->driver && drv->suspend) | 151 | if (dev->driver && drv->suspend) { |
| 133 | ret = drv->suspend(card); | 152 | ret = drv->suspend(card); |
| 153 | if (ret) | ||
| 154 | return ret; | ||
| 155 | } | ||
| 156 | |||
| 157 | ret = host->bus_ops->suspend(host); | ||
| 134 | return ret; | 158 | return ret; |
| 135 | } | 159 | } |
| 136 | 160 | ||
| @@ -138,10 +162,17 @@ static int mmc_bus_resume(struct device *dev) | |||
| 138 | { | 162 | { |
| 139 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 163 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
| 140 | struct mmc_card *card = mmc_dev_to_card(dev); | 164 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 141 | int ret = 0; | 165 | struct mmc_host *host = card->host; |
| 166 | int ret; | ||
| 167 | |||
| 168 | ret = host->bus_ops->resume(host); | ||
| 169 | if (ret) | ||
| 170 | pr_warn("%s: error %d during resume (card was removed?)\n", | ||
| 171 | mmc_hostname(host), ret); | ||
| 142 | 172 | ||
| 143 | if (dev->driver && drv->resume) | 173 | if (dev->driver && drv->resume) |
| 144 | ret = drv->resume(card); | 174 | ret = drv->resume(card); |
| 175 | |||
| 145 | return ret; | 176 | return ret; |
| 146 | } | 177 | } |
| 147 | #endif | 178 | #endif |
| @@ -151,15 +182,25 @@ static int mmc_bus_resume(struct device *dev) | |||
| 151 | static int mmc_runtime_suspend(struct device *dev) | 182 | static int mmc_runtime_suspend(struct device *dev) |
| 152 | { | 183 | { |
| 153 | struct mmc_card *card = mmc_dev_to_card(dev); | 184 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 185 | struct mmc_host *host = card->host; | ||
| 186 | int ret = 0; | ||
| 187 | |||
| 188 | if (host->bus_ops->runtime_suspend) | ||
| 189 | ret = host->bus_ops->runtime_suspend(host); | ||
| 154 | 190 | ||
| 155 | return mmc_power_save_host(card->host); | 191 | return ret; |
| 156 | } | 192 | } |
| 157 | 193 | ||
| 158 | static int mmc_runtime_resume(struct device *dev) | 194 | static int mmc_runtime_resume(struct device *dev) |
| 159 | { | 195 | { |
| 160 | struct mmc_card *card = mmc_dev_to_card(dev); | 196 | struct mmc_card *card = mmc_dev_to_card(dev); |
| 197 | struct mmc_host *host = card->host; | ||
| 198 | int ret = 0; | ||
| 199 | |||
| 200 | if (host->bus_ops->runtime_resume) | ||
| 201 | ret = host->bus_ops->runtime_resume(host); | ||
| 161 | 202 | ||
| 162 | return mmc_power_restore_host(card->host); | 203 | return ret; |
| 163 | } | 204 | } |
| 164 | 205 | ||
| 165 | static int mmc_runtime_idle(struct device *dev) | 206 | static int mmc_runtime_idle(struct device *dev) |
| @@ -182,6 +223,7 @@ static struct bus_type mmc_bus_type = { | |||
| 182 | .uevent = mmc_bus_uevent, | 223 | .uevent = mmc_bus_uevent, |
| 183 | .probe = mmc_bus_probe, | 224 | .probe = mmc_bus_probe, |
| 184 | .remove = mmc_bus_remove, | 225 | .remove = mmc_bus_remove, |
| 226 | .shutdown = mmc_bus_shutdown, | ||
| 185 | .pm = &mmc_bus_pm_ops, | 227 | .pm = &mmc_bus_pm_ops, |
| 186 | }; | 228 | }; |
| 187 | 229 | ||
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index c40396f23202..49a5bca418bd 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -402,6 +402,7 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host, | |||
| 402 | context_info->is_done_rcv = false; | 402 | context_info->is_done_rcv = false; |
| 403 | context_info->is_new_req = false; | 403 | context_info->is_new_req = false; |
| 404 | cmd = mrq->cmd; | 404 | cmd = mrq->cmd; |
| 405 | |||
| 405 | if (!cmd->error || !cmd->retries || | 406 | if (!cmd->error || !cmd->retries || |
| 406 | mmc_card_removed(host->card)) { | 407 | mmc_card_removed(host->card)) { |
| 407 | err = host->areq->err_check(host->card, | 408 | err = host->areq->err_check(host->card, |
| @@ -436,6 +437,24 @@ static void mmc_wait_for_req_done(struct mmc_host *host, | |||
| 436 | wait_for_completion(&mrq->completion); | 437 | wait_for_completion(&mrq->completion); |
| 437 | 438 | ||
| 438 | cmd = mrq->cmd; | 439 | cmd = mrq->cmd; |
| 440 | |||
| 441 | /* | ||
| 442 | * If host has timed out waiting for the sanitize | ||
| 443 | * to complete, card might be still in programming state | ||
| 444 | * so let's try to bring the card out of programming | ||
| 445 | * state. | ||
| 446 | */ | ||
| 447 | if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT) { | ||
| 448 | if (!mmc_interrupt_hpi(host->card)) { | ||
| 449 | pr_warning("%s: %s: Interrupted sanitize\n", | ||
| 450 | mmc_hostname(host), __func__); | ||
| 451 | cmd->error = 0; | ||
| 452 | break; | ||
| 453 | } else { | ||
| 454 | pr_err("%s: %s: Failed to interrupt sanitize\n", | ||
| 455 | mmc_hostname(host), __func__); | ||
| 456 | } | ||
| 457 | } | ||
| 439 | if (!cmd->error || !cmd->retries || | 458 | if (!cmd->error || !cmd->retries || |
| 440 | mmc_card_removed(host->card)) | 459 | mmc_card_removed(host->card)) |
| 441 | break; | 460 | break; |
| @@ -952,6 +971,29 @@ void mmc_release_host(struct mmc_host *host) | |||
| 952 | EXPORT_SYMBOL(mmc_release_host); | 971 | EXPORT_SYMBOL(mmc_release_host); |
| 953 | 972 | ||
| 954 | /* | 973 | /* |
| 974 | * This is a helper function, which fetches a runtime pm reference for the | ||
| 975 | * card device and also claims the host. | ||
| 976 | */ | ||
| 977 | void mmc_get_card(struct mmc_card *card) | ||
| 978 | { | ||
| 979 | pm_runtime_get_sync(&card->dev); | ||
| 980 | mmc_claim_host(card->host); | ||
| 981 | } | ||
| 982 | EXPORT_SYMBOL(mmc_get_card); | ||
| 983 | |||
| 984 | /* | ||
| 985 | * This is a helper function, which releases the host and drops the runtime | ||
| 986 | * pm reference for the card device. | ||
| 987 | */ | ||
| 988 | void mmc_put_card(struct mmc_card *card) | ||
| 989 | { | ||
| 990 | mmc_release_host(card->host); | ||
| 991 | pm_runtime_mark_last_busy(&card->dev); | ||
| 992 | pm_runtime_put_autosuspend(&card->dev); | ||
| 993 | } | ||
| 994 | EXPORT_SYMBOL(mmc_put_card); | ||
| 995 | |||
| 996 | /* | ||
| 955 | * Internal function that does the actual ios call to the host driver, | 997 | * Internal function that does the actual ios call to the host driver, |
| 956 | * optionally printing some debug output. | 998 | * optionally printing some debug output. |
| 957 | */ | 999 | */ |
| @@ -1459,7 +1501,7 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type) | |||
| 1459 | * If a host does all the power sequencing itself, ignore the | 1501 | * If a host does all the power sequencing itself, ignore the |
| 1460 | * initial MMC_POWER_UP stage. | 1502 | * initial MMC_POWER_UP stage. |
| 1461 | */ | 1503 | */ |
| 1462 | static void mmc_power_up(struct mmc_host *host) | 1504 | void mmc_power_up(struct mmc_host *host) |
| 1463 | { | 1505 | { |
| 1464 | int bit; | 1506 | int bit; |
| 1465 | 1507 | ||
| @@ -2325,14 +2367,13 @@ int mmc_detect_card_removed(struct mmc_host *host) | |||
| 2325 | * The card will be considered unchanged unless we have been asked to | 2367 | * The card will be considered unchanged unless we have been asked to |
| 2326 | * detect a change or host requires polling to provide card detection. | 2368 | * detect a change or host requires polling to provide card detection. |
| 2327 | */ | 2369 | */ |
| 2328 | if (!host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL) && | 2370 | if (!host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL)) |
| 2329 | !(host->caps2 & MMC_CAP2_DETECT_ON_ERR)) | ||
| 2330 | return ret; | 2371 | return ret; |
| 2331 | 2372 | ||
| 2332 | host->detect_change = 0; | 2373 | host->detect_change = 0; |
| 2333 | if (!ret) { | 2374 | if (!ret) { |
| 2334 | ret = _mmc_detect_card_removed(host); | 2375 | ret = _mmc_detect_card_removed(host); |
| 2335 | if (ret && (host->caps2 & MMC_CAP2_DETECT_ON_ERR)) { | 2376 | if (ret && (host->caps & MMC_CAP_NEEDS_POLL)) { |
| 2336 | /* | 2377 | /* |
| 2337 | * Schedule a detect work as soon as possible to let a | 2378 | * Schedule a detect work as soon as possible to let a |
| 2338 | * rescan handle the card removal. | 2379 | * rescan handle the card removal. |
| @@ -2442,9 +2483,7 @@ void mmc_stop_host(struct mmc_host *host) | |||
| 2442 | mmc_bus_get(host); | 2483 | mmc_bus_get(host); |
| 2443 | if (host->bus_ops && !host->bus_dead) { | 2484 | if (host->bus_ops && !host->bus_dead) { |
| 2444 | /* Calling bus_ops->remove() with a claimed host can deadlock */ | 2485 | /* Calling bus_ops->remove() with a claimed host can deadlock */ |
| 2445 | if (host->bus_ops->remove) | 2486 | host->bus_ops->remove(host); |
| 2446 | host->bus_ops->remove(host); | ||
| 2447 | |||
| 2448 | mmc_claim_host(host); | 2487 | mmc_claim_host(host); |
| 2449 | mmc_detach_bus(host); | 2488 | mmc_detach_bus(host); |
| 2450 | mmc_power_off(host); | 2489 | mmc_power_off(host); |
| @@ -2509,52 +2548,6 @@ int mmc_power_restore_host(struct mmc_host *host) | |||
| 2509 | } | 2548 | } |
| 2510 | EXPORT_SYMBOL(mmc_power_restore_host); | 2549 | EXPORT_SYMBOL(mmc_power_restore_host); |
| 2511 | 2550 | ||
| 2512 | int mmc_card_awake(struct mmc_host *host) | ||
| 2513 | { | ||
| 2514 | int err = -ENOSYS; | ||
| 2515 | |||
| 2516 | if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD) | ||
| 2517 | return 0; | ||
| 2518 | |||
| 2519 | mmc_bus_get(host); | ||
| 2520 | |||
| 2521 | if (host->bus_ops && !host->bus_dead && host->bus_ops->awake) | ||
| 2522 | err = host->bus_ops->awake(host); | ||
| 2523 | |||
| 2524 | mmc_bus_put(host); | ||
| 2525 | |||
| 2526 | return err; | ||
| 2527 | } | ||
| 2528 | EXPORT_SYMBOL(mmc_card_awake); | ||
| 2529 | |||
| 2530 | int mmc_card_sleep(struct mmc_host *host) | ||
| 2531 | { | ||
| 2532 | int err = -ENOSYS; | ||
| 2533 | |||
| 2534 | if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD) | ||
| 2535 | return 0; | ||
| 2536 | |||
| 2537 | mmc_bus_get(host); | ||
| 2538 | |||
| 2539 | if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep) | ||
| 2540 | err = host->bus_ops->sleep(host); | ||
| 2541 | |||
| 2542 | mmc_bus_put(host); | ||
| 2543 | |||
| 2544 | return err; | ||
| 2545 | } | ||
| 2546 | EXPORT_SYMBOL(mmc_card_sleep); | ||
| 2547 | |||
| 2548 | int mmc_card_can_sleep(struct mmc_host *host) | ||
| 2549 | { | ||
| 2550 | struct mmc_card *card = host->card; | ||
| 2551 | |||
| 2552 | if (card && mmc_card_mmc(card) && card->ext_csd.rev >= 3) | ||
| 2553 | return 1; | ||
| 2554 | return 0; | ||
| 2555 | } | ||
| 2556 | EXPORT_SYMBOL(mmc_card_can_sleep); | ||
| 2557 | |||
| 2558 | /* | 2551 | /* |
| 2559 | * Flush the cache to the non-volatile storage. | 2552 | * Flush the cache to the non-volatile storage. |
| 2560 | */ | 2553 | */ |
| @@ -2626,48 +2619,9 @@ EXPORT_SYMBOL(mmc_cache_ctrl); | |||
| 2626 | */ | 2619 | */ |
| 2627 | int mmc_suspend_host(struct mmc_host *host) | 2620 | int mmc_suspend_host(struct mmc_host *host) |
| 2628 | { | 2621 | { |
| 2629 | int err = 0; | 2622 | /* This function is deprecated */ |
| 2630 | 2623 | return 0; | |
| 2631 | cancel_delayed_work(&host->detect); | ||
| 2632 | mmc_flush_scheduled_work(); | ||
| 2633 | |||
| 2634 | mmc_bus_get(host); | ||
| 2635 | if (host->bus_ops && !host->bus_dead) { | ||
| 2636 | if (host->bus_ops->suspend) { | ||
| 2637 | if (mmc_card_doing_bkops(host->card)) { | ||
| 2638 | err = mmc_stop_bkops(host->card); | ||
| 2639 | if (err) | ||
| 2640 | goto out; | ||
| 2641 | } | ||
| 2642 | err = host->bus_ops->suspend(host); | ||
| 2643 | } | ||
| 2644 | |||
| 2645 | if (err == -ENOSYS || !host->bus_ops->resume) { | ||
| 2646 | /* | ||
| 2647 | * We simply "remove" the card in this case. | ||
| 2648 | * It will be redetected on resume. (Calling | ||
| 2649 | * bus_ops->remove() with a claimed host can | ||
| 2650 | * deadlock.) | ||
| 2651 | */ | ||
| 2652 | if (host->bus_ops->remove) | ||
| 2653 | host->bus_ops->remove(host); | ||
| 2654 | mmc_claim_host(host); | ||
| 2655 | mmc_detach_bus(host); | ||
| 2656 | mmc_power_off(host); | ||
| 2657 | mmc_release_host(host); | ||
| 2658 | host->pm_flags = 0; | ||
| 2659 | err = 0; | ||
| 2660 | } | ||
| 2661 | } | ||
| 2662 | mmc_bus_put(host); | ||
| 2663 | |||
| 2664 | if (!err && !mmc_card_keep_power(host)) | ||
| 2665 | mmc_power_off(host); | ||
| 2666 | |||
| 2667 | out: | ||
| 2668 | return err; | ||
| 2669 | } | 2624 | } |
| 2670 | |||
| 2671 | EXPORT_SYMBOL(mmc_suspend_host); | 2625 | EXPORT_SYMBOL(mmc_suspend_host); |
| 2672 | 2626 | ||
| 2673 | /** | 2627 | /** |
| @@ -2676,39 +2630,8 @@ EXPORT_SYMBOL(mmc_suspend_host); | |||
| 2676 | */ | 2630 | */ |
| 2677 | int mmc_resume_host(struct mmc_host *host) | 2631 | int mmc_resume_host(struct mmc_host *host) |
| 2678 | { | 2632 | { |
| 2679 | int err = 0; | 2633 | /* This function is deprecated */ |
| 2680 | 2634 | return 0; | |
| 2681 | mmc_bus_get(host); | ||
| 2682 | if (host->bus_ops && !host->bus_dead) { | ||
| 2683 | if (!mmc_card_keep_power(host)) { | ||
| 2684 | mmc_power_up(host); | ||
| 2685 | mmc_select_voltage(host, host->ocr); | ||
| 2686 | /* | ||
| 2687 | * Tell runtime PM core we just powered up the card, | ||
| 2688 | * since it still believes the card is powered off. | ||
| 2689 | * Note that currently runtime PM is only enabled | ||
| 2690 | * for SDIO cards that are MMC_CAP_POWER_OFF_CARD | ||
| 2691 | */ | ||
| 2692 | if (mmc_card_sdio(host->card) && | ||
| 2693 | (host->caps & MMC_CAP_POWER_OFF_CARD)) { | ||
| 2694 | pm_runtime_disable(&host->card->dev); | ||
| 2695 | pm_runtime_set_active(&host->card->dev); | ||
| 2696 | pm_runtime_enable(&host->card->dev); | ||
| 2697 | } | ||
| 2698 | } | ||
| 2699 | BUG_ON(!host->bus_ops->resume); | ||
| 2700 | err = host->bus_ops->resume(host); | ||
| 2701 | if (err) { | ||
| 2702 | pr_warning("%s: error %d during resume " | ||
| 2703 | "(card was removed?)\n", | ||
| 2704 | mmc_hostname(host), err); | ||
| 2705 | err = 0; | ||
| 2706 | } | ||
| 2707 | } | ||
| 2708 | host->pm_flags &= ~MMC_PM_KEEP_POWER; | ||
| 2709 | mmc_bus_put(host); | ||
| 2710 | |||
| 2711 | return err; | ||
| 2712 | } | 2635 | } |
| 2713 | EXPORT_SYMBOL(mmc_resume_host); | 2636 | EXPORT_SYMBOL(mmc_resume_host); |
| 2714 | 2637 | ||
| @@ -2727,29 +2650,22 @@ int mmc_pm_notify(struct notifier_block *notify_block, | |||
| 2727 | switch (mode) { | 2650 | switch (mode) { |
| 2728 | case PM_HIBERNATION_PREPARE: | 2651 | case PM_HIBERNATION_PREPARE: |
| 2729 | case PM_SUSPEND_PREPARE: | 2652 | case PM_SUSPEND_PREPARE: |
| 2730 | if (host->card && mmc_card_mmc(host->card) && | ||
| 2731 | mmc_card_doing_bkops(host->card)) { | ||
| 2732 | err = mmc_stop_bkops(host->card); | ||
| 2733 | if (err) { | ||
| 2734 | pr_err("%s: didn't stop bkops\n", | ||
| 2735 | mmc_hostname(host)); | ||
| 2736 | return err; | ||
| 2737 | } | ||
| 2738 | mmc_card_clr_doing_bkops(host->card); | ||
| 2739 | } | ||
| 2740 | |||
| 2741 | spin_lock_irqsave(&host->lock, flags); | 2653 | spin_lock_irqsave(&host->lock, flags); |
| 2742 | host->rescan_disable = 1; | 2654 | host->rescan_disable = 1; |
| 2743 | spin_unlock_irqrestore(&host->lock, flags); | 2655 | spin_unlock_irqrestore(&host->lock, flags); |
| 2744 | cancel_delayed_work_sync(&host->detect); | 2656 | cancel_delayed_work_sync(&host->detect); |
| 2745 | 2657 | ||
| 2746 | if (!host->bus_ops || host->bus_ops->suspend) | 2658 | if (!host->bus_ops) |
| 2747 | break; | 2659 | break; |
| 2748 | 2660 | ||
| 2749 | /* Calling bus_ops->remove() with a claimed host can deadlock */ | 2661 | /* Validate prerequisites for suspend */ |
| 2750 | if (host->bus_ops->remove) | 2662 | if (host->bus_ops->pre_suspend) |
| 2751 | host->bus_ops->remove(host); | 2663 | err = host->bus_ops->pre_suspend(host); |
| 2664 | if (!err && host->bus_ops->suspend) | ||
| 2665 | break; | ||
| 2752 | 2666 | ||
| 2667 | /* Calling bus_ops->remove() with a claimed host can deadlock */ | ||
| 2668 | host->bus_ops->remove(host); | ||
| 2753 | mmc_claim_host(host); | 2669 | mmc_claim_host(host); |
| 2754 | mmc_detach_bus(host); | 2670 | mmc_detach_bus(host); |
| 2755 | mmc_power_off(host); | 2671 | mmc_power_off(host); |
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index b9f18a2a8874..5345d156493e 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
| @@ -16,15 +16,17 @@ | |||
| 16 | #define MMC_CMD_RETRIES 3 | 16 | #define MMC_CMD_RETRIES 3 |
| 17 | 17 | ||
| 18 | struct mmc_bus_ops { | 18 | struct mmc_bus_ops { |
| 19 | int (*awake)(struct mmc_host *); | ||
| 20 | int (*sleep)(struct mmc_host *); | ||
| 21 | void (*remove)(struct mmc_host *); | 19 | void (*remove)(struct mmc_host *); |
| 22 | void (*detect)(struct mmc_host *); | 20 | void (*detect)(struct mmc_host *); |
| 21 | int (*pre_suspend)(struct mmc_host *); | ||
| 23 | int (*suspend)(struct mmc_host *); | 22 | int (*suspend)(struct mmc_host *); |
| 24 | int (*resume)(struct mmc_host *); | 23 | int (*resume)(struct mmc_host *); |
| 24 | int (*runtime_suspend)(struct mmc_host *); | ||
| 25 | int (*runtime_resume)(struct mmc_host *); | ||
| 25 | int (*power_save)(struct mmc_host *); | 26 | int (*power_save)(struct mmc_host *); |
| 26 | int (*power_restore)(struct mmc_host *); | 27 | int (*power_restore)(struct mmc_host *); |
| 27 | int (*alive)(struct mmc_host *); | 28 | int (*alive)(struct mmc_host *); |
| 29 | int (*shutdown)(struct mmc_host *); | ||
| 28 | }; | 30 | }; |
| 29 | 31 | ||
| 30 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); | 32 | void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); |
| @@ -44,6 +46,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); | |||
| 44 | int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); | 46 | int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); |
| 45 | void mmc_set_timing(struct mmc_host *host, unsigned int timing); | 47 | void mmc_set_timing(struct mmc_host *host, unsigned int timing); |
| 46 | void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); | 48 | void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); |
| 49 | void mmc_power_up(struct mmc_host *host); | ||
| 47 | void mmc_power_off(struct mmc_host *host); | 50 | void mmc_power_off(struct mmc_host *host); |
| 48 | void mmc_power_cycle(struct mmc_host *host); | 51 | void mmc_power_cycle(struct mmc_host *host); |
| 49 | 52 | ||
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 35c2f85b1956..54829c0ed000 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c | |||
| @@ -258,13 +258,13 @@ static int mmc_dbg_card_status_get(void *data, u64 *val) | |||
| 258 | u32 status; | 258 | u32 status; |
| 259 | int ret; | 259 | int ret; |
| 260 | 260 | ||
| 261 | mmc_claim_host(card->host); | 261 | mmc_get_card(card); |
| 262 | 262 | ||
| 263 | ret = mmc_send_status(data, &status); | 263 | ret = mmc_send_status(data, &status); |
| 264 | if (!ret) | 264 | if (!ret) |
| 265 | *val = status; | 265 | *val = status; |
| 266 | 266 | ||
| 267 | mmc_release_host(card->host); | 267 | mmc_put_card(card); |
| 268 | 268 | ||
| 269 | return ret; | 269 | return ret; |
| 270 | } | 270 | } |
| @@ -291,9 +291,9 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp) | |||
| 291 | goto out_free; | 291 | goto out_free; |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | mmc_claim_host(card->host); | 294 | mmc_get_card(card); |
| 295 | err = mmc_send_ext_csd(card, ext_csd); | 295 | err = mmc_send_ext_csd(card, ext_csd); |
| 296 | mmc_release_host(card->host); | 296 | mmc_put_card(card); |
| 297 | if (err) | 297 | if (err) |
| 298 | goto out_free; | 298 | goto out_free; |
| 299 | 299 | ||
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 2a3593d9f87d..6fb6f77450cb 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
| @@ -306,7 +306,7 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) | |||
| 306 | * parse the properties and set respective generic mmc-host flags and | 306 | * parse the properties and set respective generic mmc-host flags and |
| 307 | * parameters. | 307 | * parameters. |
| 308 | */ | 308 | */ |
| 309 | void mmc_of_parse(struct mmc_host *host) | 309 | int mmc_of_parse(struct mmc_host *host) |
| 310 | { | 310 | { |
| 311 | struct device_node *np; | 311 | struct device_node *np; |
| 312 | u32 bus_width; | 312 | u32 bus_width; |
| @@ -315,7 +315,7 @@ void mmc_of_parse(struct mmc_host *host) | |||
| 315 | int len, ret, gpio; | 315 | int len, ret, gpio; |
| 316 | 316 | ||
| 317 | if (!host->parent || !host->parent->of_node) | 317 | if (!host->parent || !host->parent->of_node) |
| 318 | return; | 318 | return 0; |
| 319 | 319 | ||
| 320 | np = host->parent->of_node; | 320 | np = host->parent->of_node; |
| 321 | 321 | ||
| @@ -338,6 +338,7 @@ void mmc_of_parse(struct mmc_host *host) | |||
| 338 | default: | 338 | default: |
| 339 | dev_err(host->parent, | 339 | dev_err(host->parent, |
| 340 | "Invalid \"bus-width\" value %ud!\n", bus_width); | 340 | "Invalid \"bus-width\" value %ud!\n", bus_width); |
| 341 | return -EINVAL; | ||
| 341 | } | 342 | } |
| 342 | 343 | ||
| 343 | /* f_max is obtained from the optional "max-frequency" property */ | 344 | /* f_max is obtained from the optional "max-frequency" property */ |
| @@ -367,18 +368,22 @@ void mmc_of_parse(struct mmc_host *host) | |||
| 367 | host->caps |= MMC_CAP_NEEDS_POLL; | 368 | host->caps |= MMC_CAP_NEEDS_POLL; |
| 368 | 369 | ||
| 369 | gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &flags); | 370 | gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &flags); |
| 371 | if (gpio == -EPROBE_DEFER) | ||
| 372 | return gpio; | ||
| 370 | if (gpio_is_valid(gpio)) { | 373 | if (gpio_is_valid(gpio)) { |
| 371 | if (!(flags & OF_GPIO_ACTIVE_LOW)) | 374 | if (!(flags & OF_GPIO_ACTIVE_LOW)) |
| 372 | gpio_inv_cd = true; | 375 | gpio_inv_cd = true; |
| 373 | 376 | ||
| 374 | ret = mmc_gpio_request_cd(host, gpio); | 377 | ret = mmc_gpio_request_cd(host, gpio); |
| 375 | if (ret < 0) | 378 | if (ret < 0) { |
| 376 | dev_err(host->parent, | 379 | dev_err(host->parent, |
| 377 | "Failed to request CD GPIO #%d: %d!\n", | 380 | "Failed to request CD GPIO #%d: %d!\n", |
| 378 | gpio, ret); | 381 | gpio, ret); |
| 379 | else | 382 | return ret; |
| 383 | } else { | ||
| 380 | dev_info(host->parent, "Got CD GPIO #%d.\n", | 384 | dev_info(host->parent, "Got CD GPIO #%d.\n", |
| 381 | gpio); | 385 | gpio); |
| 386 | } | ||
| 382 | } | 387 | } |
| 383 | 388 | ||
| 384 | if (explicit_inv_cd ^ gpio_inv_cd) | 389 | if (explicit_inv_cd ^ gpio_inv_cd) |
| @@ -389,14 +394,23 @@ void mmc_of_parse(struct mmc_host *host) | |||
| 389 | explicit_inv_wp = of_property_read_bool(np, "wp-inverted"); | 394 | explicit_inv_wp = of_property_read_bool(np, "wp-inverted"); |
| 390 | 395 | ||
| 391 | gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags); | 396 | gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags); |
| 397 | if (gpio == -EPROBE_DEFER) { | ||
| 398 | ret = -EPROBE_DEFER; | ||
| 399 | goto out; | ||
| 400 | } | ||
| 392 | if (gpio_is_valid(gpio)) { | 401 | if (gpio_is_valid(gpio)) { |
| 393 | if (!(flags & OF_GPIO_ACTIVE_LOW)) | 402 | if (!(flags & OF_GPIO_ACTIVE_LOW)) |
| 394 | gpio_inv_wp = true; | 403 | gpio_inv_wp = true; |
| 395 | 404 | ||
| 396 | ret = mmc_gpio_request_ro(host, gpio); | 405 | ret = mmc_gpio_request_ro(host, gpio); |
| 397 | if (ret < 0) | 406 | if (ret < 0) { |
| 398 | dev_err(host->parent, | 407 | dev_err(host->parent, |
| 399 | "Failed to request WP GPIO: %d!\n", ret); | 408 | "Failed to request WP GPIO: %d!\n", ret); |
| 409 | goto out; | ||
| 410 | } else { | ||
| 411 | dev_info(host->parent, "Got WP GPIO #%d.\n", | ||
| 412 | gpio); | ||
| 413 | } | ||
| 400 | } | 414 | } |
| 401 | if (explicit_inv_wp ^ gpio_inv_wp) | 415 | if (explicit_inv_wp ^ gpio_inv_wp) |
| 402 | host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; | 416 | host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; |
| @@ -409,10 +423,18 @@ void mmc_of_parse(struct mmc_host *host) | |||
| 409 | host->caps |= MMC_CAP_POWER_OFF_CARD; | 423 | host->caps |= MMC_CAP_POWER_OFF_CARD; |
| 410 | if (of_find_property(np, "cap-sdio-irq", &len)) | 424 | if (of_find_property(np, "cap-sdio-irq", &len)) |
| 411 | host->caps |= MMC_CAP_SDIO_IRQ; | 425 | host->caps |= MMC_CAP_SDIO_IRQ; |
| 426 | if (of_find_property(np, "full-pwr-cycle", &len)) | ||
| 427 | host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE; | ||
| 412 | if (of_find_property(np, "keep-power-in-suspend", &len)) | 428 | if (of_find_property(np, "keep-power-in-suspend", &len)) |
| 413 | host->pm_caps |= MMC_PM_KEEP_POWER; | 429 | host->pm_caps |= MMC_PM_KEEP_POWER; |
| 414 | if (of_find_property(np, "enable-sdio-wakeup", &len)) | 430 | if (of_find_property(np, "enable-sdio-wakeup", &len)) |
| 415 | host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; | 431 | host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; |
| 432 | |||
| 433 | return 0; | ||
| 434 | |||
| 435 | out: | ||
| 436 | mmc_gpio_free_cd(host); | ||
| 437 | return ret; | ||
| 416 | } | 438 | } |
| 417 | 439 | ||
| 418 | EXPORT_SYMBOL(mmc_of_parse); | 440 | EXPORT_SYMBOL(mmc_of_parse); |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 0cbd1effe960..6d02012a1d0b 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
| @@ -293,7 +293,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | card->ext_csd.rev = ext_csd[EXT_CSD_REV]; | 295 | card->ext_csd.rev = ext_csd[EXT_CSD_REV]; |
| 296 | if (card->ext_csd.rev > 6) { | 296 | if (card->ext_csd.rev > 7) { |
| 297 | pr_err("%s: unrecognised EXT_CSD revision %d\n", | 297 | pr_err("%s: unrecognised EXT_CSD revision %d\n", |
| 298 | mmc_hostname(card->host), card->ext_csd.rev); | 298 | mmc_hostname(card->host), card->ext_csd.rev); |
| 299 | err = -EINVAL; | 299 | err = -EINVAL; |
| @@ -461,9 +461,31 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
| 461 | */ | 461 | */ |
| 462 | card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP]; | 462 | card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP]; |
| 463 | card->ext_csd.boot_ro_lockable = true; | 463 | card->ext_csd.boot_ro_lockable = true; |
| 464 | |||
| 465 | /* Save power class values */ | ||
| 466 | card->ext_csd.raw_pwr_cl_52_195 = | ||
| 467 | ext_csd[EXT_CSD_PWR_CL_52_195]; | ||
| 468 | card->ext_csd.raw_pwr_cl_26_195 = | ||
| 469 | ext_csd[EXT_CSD_PWR_CL_26_195]; | ||
| 470 | card->ext_csd.raw_pwr_cl_52_360 = | ||
| 471 | ext_csd[EXT_CSD_PWR_CL_52_360]; | ||
| 472 | card->ext_csd.raw_pwr_cl_26_360 = | ||
| 473 | ext_csd[EXT_CSD_PWR_CL_26_360]; | ||
| 474 | card->ext_csd.raw_pwr_cl_200_195 = | ||
| 475 | ext_csd[EXT_CSD_PWR_CL_200_195]; | ||
| 476 | card->ext_csd.raw_pwr_cl_200_360 = | ||
| 477 | ext_csd[EXT_CSD_PWR_CL_200_360]; | ||
| 478 | card->ext_csd.raw_pwr_cl_ddr_52_195 = | ||
| 479 | ext_csd[EXT_CSD_PWR_CL_DDR_52_195]; | ||
| 480 | card->ext_csd.raw_pwr_cl_ddr_52_360 = | ||
| 481 | ext_csd[EXT_CSD_PWR_CL_DDR_52_360]; | ||
| 464 | } | 482 | } |
| 465 | 483 | ||
| 466 | if (card->ext_csd.rev >= 5) { | 484 | if (card->ext_csd.rev >= 5) { |
| 485 | /* Adjust production date as per JEDEC JESD84-B451 */ | ||
| 486 | if (card->cid.year < 2010) | ||
| 487 | card->cid.year += 16; | ||
| 488 | |||
| 467 | /* check whether the eMMC card supports BKOPS */ | 489 | /* check whether the eMMC card supports BKOPS */ |
| 468 | if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { | 490 | if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { |
| 469 | card->ext_csd.bkops = 1; | 491 | card->ext_csd.bkops = 1; |
| @@ -607,7 +629,23 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width) | |||
| 607 | (card->ext_csd.raw_sectors[2] == | 629 | (card->ext_csd.raw_sectors[2] == |
| 608 | bw_ext_csd[EXT_CSD_SEC_CNT + 2]) && | 630 | bw_ext_csd[EXT_CSD_SEC_CNT + 2]) && |
| 609 | (card->ext_csd.raw_sectors[3] == | 631 | (card->ext_csd.raw_sectors[3] == |
| 610 | bw_ext_csd[EXT_CSD_SEC_CNT + 3])); | 632 | bw_ext_csd[EXT_CSD_SEC_CNT + 3]) && |
| 633 | (card->ext_csd.raw_pwr_cl_52_195 == | ||
| 634 | bw_ext_csd[EXT_CSD_PWR_CL_52_195]) && | ||
| 635 | (card->ext_csd.raw_pwr_cl_26_195 == | ||
| 636 | bw_ext_csd[EXT_CSD_PWR_CL_26_195]) && | ||
| 637 | (card->ext_csd.raw_pwr_cl_52_360 == | ||
| 638 | bw_ext_csd[EXT_CSD_PWR_CL_52_360]) && | ||
| 639 | (card->ext_csd.raw_pwr_cl_26_360 == | ||
| 640 | bw_ext_csd[EXT_CSD_PWR_CL_26_360]) && | ||
| 641 | (card->ext_csd.raw_pwr_cl_200_195 == | ||
| 642 | bw_ext_csd[EXT_CSD_PWR_CL_200_195]) && | ||
| 643 | (card->ext_csd.raw_pwr_cl_200_360 == | ||
| 644 | bw_ext_csd[EXT_CSD_PWR_CL_200_360]) && | ||
| 645 | (card->ext_csd.raw_pwr_cl_ddr_52_195 == | ||
| 646 | bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) && | ||
| 647 | (card->ext_csd.raw_pwr_cl_ddr_52_360 == | ||
| 648 | bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360])); | ||
| 611 | if (err) | 649 | if (err) |
| 612 | err = -EINVAL; | 650 | err = -EINVAL; |
| 613 | 651 | ||
| @@ -676,11 +714,10 @@ static struct device_type mmc_type = { | |||
| 676 | * mmc_switch command. | 714 | * mmc_switch command. |
| 677 | */ | 715 | */ |
| 678 | static int mmc_select_powerclass(struct mmc_card *card, | 716 | static int mmc_select_powerclass(struct mmc_card *card, |
| 679 | unsigned int bus_width, u8 *ext_csd) | 717 | unsigned int bus_width) |
| 680 | { | 718 | { |
| 681 | int err = 0; | 719 | int err = 0; |
| 682 | unsigned int pwrclass_val; | 720 | unsigned int pwrclass_val = 0; |
| 683 | unsigned int index = 0; | ||
| 684 | struct mmc_host *host; | 721 | struct mmc_host *host; |
| 685 | 722 | ||
| 686 | BUG_ON(!card); | 723 | BUG_ON(!card); |
| @@ -688,9 +725,6 @@ static int mmc_select_powerclass(struct mmc_card *card, | |||
| 688 | host = card->host; | 725 | host = card->host; |
| 689 | BUG_ON(!host); | 726 | BUG_ON(!host); |
| 690 | 727 | ||
| 691 | if (ext_csd == NULL) | ||
| 692 | return 0; | ||
| 693 | |||
| 694 | /* Power class selection is supported for versions >= 4.0 */ | 728 | /* Power class selection is supported for versions >= 4.0 */ |
| 695 | if (card->csd.mmca_vsn < CSD_SPEC_VER_4) | 729 | if (card->csd.mmca_vsn < CSD_SPEC_VER_4) |
| 696 | return 0; | 730 | return 0; |
| @@ -702,13 +736,13 @@ static int mmc_select_powerclass(struct mmc_card *card, | |||
| 702 | switch (1 << host->ios.vdd) { | 736 | switch (1 << host->ios.vdd) { |
| 703 | case MMC_VDD_165_195: | 737 | case MMC_VDD_165_195: |
| 704 | if (host->ios.clock <= 26000000) | 738 | if (host->ios.clock <= 26000000) |
| 705 | index = EXT_CSD_PWR_CL_26_195; | 739 | pwrclass_val = card->ext_csd.raw_pwr_cl_26_195; |
| 706 | else if (host->ios.clock <= 52000000) | 740 | else if (host->ios.clock <= 52000000) |
| 707 | index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? | 741 | pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? |
| 708 | EXT_CSD_PWR_CL_52_195 : | 742 | card->ext_csd.raw_pwr_cl_52_195 : |
| 709 | EXT_CSD_PWR_CL_DDR_52_195; | 743 | card->ext_csd.raw_pwr_cl_ddr_52_195; |
| 710 | else if (host->ios.clock <= 200000000) | 744 | else if (host->ios.clock <= 200000000) |
| 711 | index = EXT_CSD_PWR_CL_200_195; | 745 | pwrclass_val = card->ext_csd.raw_pwr_cl_200_195; |
| 712 | break; | 746 | break; |
| 713 | case MMC_VDD_27_28: | 747 | case MMC_VDD_27_28: |
| 714 | case MMC_VDD_28_29: | 748 | case MMC_VDD_28_29: |
| @@ -720,13 +754,13 @@ static int mmc_select_powerclass(struct mmc_card *card, | |||
| 720 | case MMC_VDD_34_35: | 754 | case MMC_VDD_34_35: |
| 721 | case MMC_VDD_35_36: | 755 | case MMC_VDD_35_36: |
| 722 | if (host->ios.clock <= 26000000) | 756 | if (host->ios.clock <= 26000000) |
| 723 | index = EXT_CSD_PWR_CL_26_360; | 757 | pwrclass_val = card->ext_csd.raw_pwr_cl_26_360; |
| 724 | else if (host->ios.clock <= 52000000) | 758 | else if (host->ios.clock <= 52000000) |
| 725 | index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? | 759 | pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? |
| 726 | EXT_CSD_PWR_CL_52_360 : | 760 | card->ext_csd.raw_pwr_cl_52_360 : |
| 727 | EXT_CSD_PWR_CL_DDR_52_360; | 761 | card->ext_csd.raw_pwr_cl_ddr_52_360; |
| 728 | else if (host->ios.clock <= 200000000) | 762 | else if (host->ios.clock <= 200000000) |
| 729 | index = EXT_CSD_PWR_CL_200_360; | 763 | pwrclass_val = card->ext_csd.raw_pwr_cl_200_360; |
| 730 | break; | 764 | break; |
| 731 | default: | 765 | default: |
| 732 | pr_warning("%s: Voltage range not supported " | 766 | pr_warning("%s: Voltage range not supported " |
| @@ -734,8 +768,6 @@ static int mmc_select_powerclass(struct mmc_card *card, | |||
| 734 | return -EINVAL; | 768 | return -EINVAL; |
| 735 | } | 769 | } |
| 736 | 770 | ||
| 737 | pwrclass_val = ext_csd[index]; | ||
| 738 | |||
| 739 | if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8)) | 771 | if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8)) |
| 740 | pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >> | 772 | pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >> |
| 741 | EXT_CSD_PWR_CL_8BIT_SHIFT; | 773 | EXT_CSD_PWR_CL_8BIT_SHIFT; |
| @@ -1013,11 +1045,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 1013 | } | 1045 | } |
| 1014 | 1046 | ||
| 1015 | /* | 1047 | /* |
| 1016 | * If the host supports the power_off_notify capability then | 1048 | * Enable power_off_notification byte in the ext_csd register |
| 1017 | * set the notification byte in the ext_csd register of device | ||
| 1018 | */ | 1049 | */ |
| 1019 | if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) && | 1050 | if (card->ext_csd.rev >= 6) { |
| 1020 | (card->ext_csd.rev >= 6)) { | ||
| 1021 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 1051 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 1022 | EXT_CSD_POWER_OFF_NOTIFICATION, | 1052 | EXT_CSD_POWER_OFF_NOTIFICATION, |
| 1023 | EXT_CSD_POWER_ON, | 1053 | EXT_CSD_POWER_ON, |
| @@ -1131,7 +1161,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 1131 | 1161 | ||
| 1132 | ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? | 1162 | ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? |
| 1133 | EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; | 1163 | EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; |
| 1134 | err = mmc_select_powerclass(card, ext_csd_bits, ext_csd); | 1164 | err = mmc_select_powerclass(card, ext_csd_bits); |
| 1135 | if (err) | 1165 | if (err) |
| 1136 | pr_warning("%s: power class selection to bus width %d" | 1166 | pr_warning("%s: power class selection to bus width %d" |
| 1137 | " failed\n", mmc_hostname(card->host), | 1167 | " failed\n", mmc_hostname(card->host), |
| @@ -1164,8 +1194,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 1164 | bus_width = bus_widths[idx]; | 1194 | bus_width = bus_widths[idx]; |
| 1165 | if (bus_width == MMC_BUS_WIDTH_1) | 1195 | if (bus_width == MMC_BUS_WIDTH_1) |
| 1166 | ddr = 0; /* no DDR for 1-bit width */ | 1196 | ddr = 0; /* no DDR for 1-bit width */ |
| 1167 | err = mmc_select_powerclass(card, ext_csd_bits[idx][0], | 1197 | err = mmc_select_powerclass(card, ext_csd_bits[idx][0]); |
| 1168 | ext_csd); | ||
| 1169 | if (err) | 1198 | if (err) |
| 1170 | pr_warning("%s: power class selection to " | 1199 | pr_warning("%s: power class selection to " |
| 1171 | "bus width %d failed\n", | 1200 | "bus width %d failed\n", |
| @@ -1195,8 +1224,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 1195 | } | 1224 | } |
| 1196 | 1225 | ||
| 1197 | if (!err && ddr) { | 1226 | if (!err && ddr) { |
| 1198 | err = mmc_select_powerclass(card, ext_csd_bits[idx][1], | 1227 | err = mmc_select_powerclass(card, ext_csd_bits[idx][1]); |
| 1199 | ext_csd); | ||
| 1200 | if (err) | 1228 | if (err) |
| 1201 | pr_warning("%s: power class selection to " | 1229 | pr_warning("%s: power class selection to " |
| 1202 | "bus width %d ddr %d failed\n", | 1230 | "bus width %d ddr %d failed\n", |
| @@ -1321,6 +1349,45 @@ err: | |||
| 1321 | return err; | 1349 | return err; |
| 1322 | } | 1350 | } |
| 1323 | 1351 | ||
| 1352 | static int mmc_can_sleep(struct mmc_card *card) | ||
| 1353 | { | ||
| 1354 | return (card && card->ext_csd.rev >= 3); | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | static int mmc_sleep(struct mmc_host *host) | ||
| 1358 | { | ||
| 1359 | struct mmc_command cmd = {0}; | ||
| 1360 | struct mmc_card *card = host->card; | ||
| 1361 | int err; | ||
| 1362 | |||
| 1363 | if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD) | ||
| 1364 | return 0; | ||
| 1365 | |||
| 1366 | err = mmc_deselect_cards(host); | ||
| 1367 | if (err) | ||
| 1368 | return err; | ||
| 1369 | |||
| 1370 | cmd.opcode = MMC_SLEEP_AWAKE; | ||
| 1371 | cmd.arg = card->rca << 16; | ||
| 1372 | cmd.arg |= 1 << 15; | ||
| 1373 | |||
| 1374 | cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; | ||
| 1375 | err = mmc_wait_for_cmd(host, &cmd, 0); | ||
| 1376 | if (err) | ||
| 1377 | return err; | ||
| 1378 | |||
| 1379 | /* | ||
| 1380 | * If the host does not wait while the card signals busy, then we will | ||
| 1381 | * will have to wait the sleep/awake timeout. Note, we cannot use the | ||
| 1382 | * SEND_STATUS command to poll the status because that command (and most | ||
| 1383 | * others) is invalid while the card sleeps. | ||
| 1384 | */ | ||
| 1385 | if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) | ||
| 1386 | mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); | ||
| 1387 | |||
| 1388 | return err; | ||
| 1389 | } | ||
| 1390 | |||
| 1324 | static int mmc_can_poweroff_notify(const struct mmc_card *card) | 1391 | static int mmc_can_poweroff_notify(const struct mmc_card *card) |
| 1325 | { | 1392 | { |
| 1326 | return card && | 1393 | return card && |
| @@ -1380,14 +1447,14 @@ static void mmc_detect(struct mmc_host *host) | |||
| 1380 | BUG_ON(!host); | 1447 | BUG_ON(!host); |
| 1381 | BUG_ON(!host->card); | 1448 | BUG_ON(!host->card); |
| 1382 | 1449 | ||
| 1383 | mmc_claim_host(host); | 1450 | mmc_get_card(host->card); |
| 1384 | 1451 | ||
| 1385 | /* | 1452 | /* |
| 1386 | * Just check if our card has been removed. | 1453 | * Just check if our card has been removed. |
| 1387 | */ | 1454 | */ |
| 1388 | err = _mmc_detect_card_removed(host); | 1455 | err = _mmc_detect_card_removed(host); |
| 1389 | 1456 | ||
| 1390 | mmc_release_host(host); | 1457 | mmc_put_card(host->card); |
| 1391 | 1458 | ||
| 1392 | if (err) { | 1459 | if (err) { |
| 1393 | mmc_remove(host); | 1460 | mmc_remove(host); |
| @@ -1399,36 +1466,60 @@ static void mmc_detect(struct mmc_host *host) | |||
| 1399 | } | 1466 | } |
| 1400 | } | 1467 | } |
| 1401 | 1468 | ||
| 1402 | /* | 1469 | static int _mmc_suspend(struct mmc_host *host, bool is_suspend) |
| 1403 | * Suspend callback from host. | ||
| 1404 | */ | ||
| 1405 | static int mmc_suspend(struct mmc_host *host) | ||
| 1406 | { | 1470 | { |
| 1407 | int err = 0; | 1471 | int err = 0; |
| 1472 | unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT : | ||
| 1473 | EXT_CSD_POWER_OFF_LONG; | ||
| 1408 | 1474 | ||
| 1409 | BUG_ON(!host); | 1475 | BUG_ON(!host); |
| 1410 | BUG_ON(!host->card); | 1476 | BUG_ON(!host->card); |
| 1411 | 1477 | ||
| 1412 | mmc_claim_host(host); | 1478 | mmc_claim_host(host); |
| 1413 | 1479 | ||
| 1480 | if (mmc_card_doing_bkops(host->card)) { | ||
| 1481 | err = mmc_stop_bkops(host->card); | ||
| 1482 | if (err) | ||
| 1483 | goto out; | ||
| 1484 | } | ||
| 1485 | |||
| 1414 | err = mmc_cache_ctrl(host, 0); | 1486 | err = mmc_cache_ctrl(host, 0); |
| 1415 | if (err) | 1487 | if (err) |
| 1416 | goto out; | 1488 | goto out; |
| 1417 | 1489 | ||
| 1418 | if (mmc_can_poweroff_notify(host->card)) | 1490 | if (mmc_can_poweroff_notify(host->card) && |
| 1419 | err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT); | 1491 | ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend)) |
| 1420 | else if (mmc_card_can_sleep(host)) | 1492 | err = mmc_poweroff_notify(host->card, notify_type); |
| 1421 | err = mmc_card_sleep(host); | 1493 | else if (mmc_can_sleep(host->card)) |
| 1494 | err = mmc_sleep(host); | ||
| 1422 | else if (!mmc_host_is_spi(host)) | 1495 | else if (!mmc_host_is_spi(host)) |
| 1423 | err = mmc_deselect_cards(host); | 1496 | err = mmc_deselect_cards(host); |
| 1424 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); | 1497 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); |
| 1425 | 1498 | ||
| 1499 | if (!err) | ||
| 1500 | mmc_power_off(host); | ||
| 1426 | out: | 1501 | out: |
| 1427 | mmc_release_host(host); | 1502 | mmc_release_host(host); |
| 1428 | return err; | 1503 | return err; |
| 1429 | } | 1504 | } |
| 1430 | 1505 | ||
| 1431 | /* | 1506 | /* |
| 1507 | * Suspend callback from host. | ||
| 1508 | */ | ||
| 1509 | static int mmc_suspend(struct mmc_host *host) | ||
| 1510 | { | ||
| 1511 | return _mmc_suspend(host, true); | ||
| 1512 | } | ||
| 1513 | |||
| 1514 | /* | ||
| 1515 | * Shutdown callback | ||
| 1516 | */ | ||
| 1517 | static int mmc_shutdown(struct mmc_host *host) | ||
| 1518 | { | ||
| 1519 | return _mmc_suspend(host, false); | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | /* | ||
| 1432 | * Resume callback from host. | 1523 | * Resume callback from host. |
| 1433 | * | 1524 | * |
| 1434 | * This function tries to determine if the same card is still present | 1525 | * This function tries to determine if the same card is still present |
| @@ -1442,74 +1533,94 @@ static int mmc_resume(struct mmc_host *host) | |||
| 1442 | BUG_ON(!host->card); | 1533 | BUG_ON(!host->card); |
| 1443 | 1534 | ||
| 1444 | mmc_claim_host(host); | 1535 | mmc_claim_host(host); |
| 1536 | mmc_power_up(host); | ||
| 1537 | mmc_select_voltage(host, host->ocr); | ||
| 1445 | err = mmc_init_card(host, host->ocr, host->card); | 1538 | err = mmc_init_card(host, host->ocr, host->card); |
| 1446 | mmc_release_host(host); | 1539 | mmc_release_host(host); |
| 1447 | 1540 | ||
| 1448 | return err; | 1541 | return err; |
| 1449 | } | 1542 | } |
| 1450 | 1543 | ||
| 1451 | static int mmc_power_restore(struct mmc_host *host) | 1544 | |
| 1545 | /* | ||
| 1546 | * Callback for runtime_suspend. | ||
| 1547 | */ | ||
| 1548 | static int mmc_runtime_suspend(struct mmc_host *host) | ||
| 1452 | { | 1549 | { |
| 1453 | int ret; | 1550 | int err; |
| 1551 | |||
| 1552 | if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) | ||
| 1553 | return 0; | ||
| 1454 | 1554 | ||
| 1455 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); | ||
| 1456 | mmc_claim_host(host); | 1555 | mmc_claim_host(host); |
| 1457 | ret = mmc_init_card(host, host->ocr, host->card); | ||
| 1458 | mmc_release_host(host); | ||
| 1459 | 1556 | ||
| 1460 | return ret; | 1557 | err = mmc_suspend(host); |
| 1558 | if (err) { | ||
| 1559 | pr_err("%s: error %d doing aggessive suspend\n", | ||
| 1560 | mmc_hostname(host), err); | ||
| 1561 | goto out; | ||
| 1562 | } | ||
| 1563 | mmc_power_off(host); | ||
| 1564 | |||
| 1565 | out: | ||
| 1566 | mmc_release_host(host); | ||
| 1567 | return err; | ||
| 1461 | } | 1568 | } |
| 1462 | 1569 | ||
| 1463 | static int mmc_sleep(struct mmc_host *host) | 1570 | /* |
| 1571 | * Callback for runtime_resume. | ||
| 1572 | */ | ||
| 1573 | static int mmc_runtime_resume(struct mmc_host *host) | ||
| 1464 | { | 1574 | { |
| 1465 | struct mmc_card *card = host->card; | 1575 | int err; |
| 1466 | int err = -ENOSYS; | ||
| 1467 | 1576 | ||
| 1468 | if (card && card->ext_csd.rev >= 3) { | 1577 | if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) |
| 1469 | err = mmc_card_sleepawake(host, 1); | 1578 | return 0; |
| 1470 | if (err < 0) | ||
| 1471 | pr_debug("%s: Error %d while putting card into sleep", | ||
| 1472 | mmc_hostname(host), err); | ||
| 1473 | } | ||
| 1474 | 1579 | ||
| 1475 | return err; | 1580 | mmc_claim_host(host); |
| 1581 | |||
| 1582 | mmc_power_up(host); | ||
| 1583 | err = mmc_resume(host); | ||
| 1584 | if (err) | ||
| 1585 | pr_err("%s: error %d doing aggessive resume\n", | ||
| 1586 | mmc_hostname(host), err); | ||
| 1587 | |||
| 1588 | mmc_release_host(host); | ||
| 1589 | return 0; | ||
| 1476 | } | 1590 | } |
| 1477 | 1591 | ||
| 1478 | static int mmc_awake(struct mmc_host *host) | 1592 | static int mmc_power_restore(struct mmc_host *host) |
| 1479 | { | 1593 | { |
| 1480 | struct mmc_card *card = host->card; | 1594 | int ret; |
| 1481 | int err = -ENOSYS; | ||
| 1482 | 1595 | ||
| 1483 | if (card && card->ext_csd.rev >= 3) { | 1596 | host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); |
| 1484 | err = mmc_card_sleepawake(host, 0); | 1597 | mmc_claim_host(host); |
| 1485 | if (err < 0) | 1598 | ret = mmc_init_card(host, host->ocr, host->card); |
| 1486 | pr_debug("%s: Error %d while awaking sleeping card", | 1599 | mmc_release_host(host); |
| 1487 | mmc_hostname(host), err); | ||
| 1488 | } | ||
| 1489 | 1600 | ||
| 1490 | return err; | 1601 | return ret; |
| 1491 | } | 1602 | } |
| 1492 | 1603 | ||
| 1493 | static const struct mmc_bus_ops mmc_ops = { | 1604 | static const struct mmc_bus_ops mmc_ops = { |
| 1494 | .awake = mmc_awake, | ||
| 1495 | .sleep = mmc_sleep, | ||
| 1496 | .remove = mmc_remove, | 1605 | .remove = mmc_remove, |
| 1497 | .detect = mmc_detect, | 1606 | .detect = mmc_detect, |
| 1498 | .suspend = NULL, | 1607 | .suspend = NULL, |
| 1499 | .resume = NULL, | 1608 | .resume = NULL, |
| 1500 | .power_restore = mmc_power_restore, | 1609 | .power_restore = mmc_power_restore, |
| 1501 | .alive = mmc_alive, | 1610 | .alive = mmc_alive, |
| 1611 | .shutdown = mmc_shutdown, | ||
| 1502 | }; | 1612 | }; |
| 1503 | 1613 | ||
| 1504 | static const struct mmc_bus_ops mmc_ops_unsafe = { | 1614 | static const struct mmc_bus_ops mmc_ops_unsafe = { |
| 1505 | .awake = mmc_awake, | ||
| 1506 | .sleep = mmc_sleep, | ||
| 1507 | .remove = mmc_remove, | 1615 | .remove = mmc_remove, |
| 1508 | .detect = mmc_detect, | 1616 | .detect = mmc_detect, |
| 1509 | .suspend = mmc_suspend, | 1617 | .suspend = mmc_suspend, |
| 1510 | .resume = mmc_resume, | 1618 | .resume = mmc_resume, |
| 1619 | .runtime_suspend = mmc_runtime_suspend, | ||
| 1620 | .runtime_resume = mmc_runtime_resume, | ||
| 1511 | .power_restore = mmc_power_restore, | 1621 | .power_restore = mmc_power_restore, |
| 1512 | .alive = mmc_alive, | 1622 | .alive = mmc_alive, |
| 1623 | .shutdown = mmc_shutdown, | ||
| 1513 | }; | 1624 | }; |
| 1514 | 1625 | ||
| 1515 | static void mmc_attach_bus_ops(struct mmc_host *host) | 1626 | static void mmc_attach_bus_ops(struct mmc_host *host) |
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 49f04bc9d0eb..837fc7386e23 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c | |||
| @@ -59,40 +59,6 @@ int mmc_deselect_cards(struct mmc_host *host) | |||
| 59 | return _mmc_select_card(host, NULL); | 59 | return _mmc_select_card(host, NULL); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | int mmc_card_sleepawake(struct mmc_host *host, int sleep) | ||
| 63 | { | ||
| 64 | struct mmc_command cmd = {0}; | ||
| 65 | struct mmc_card *card = host->card; | ||
| 66 | int err; | ||
| 67 | |||
| 68 | if (sleep) | ||
| 69 | mmc_deselect_cards(host); | ||
| 70 | |||
| 71 | cmd.opcode = MMC_SLEEP_AWAKE; | ||
| 72 | cmd.arg = card->rca << 16; | ||
| 73 | if (sleep) | ||
| 74 | cmd.arg |= 1 << 15; | ||
| 75 | |||
| 76 | cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; | ||
| 77 | err = mmc_wait_for_cmd(host, &cmd, 0); | ||
| 78 | if (err) | ||
| 79 | return err; | ||
| 80 | |||
| 81 | /* | ||
| 82 | * If the host does not wait while the card signals busy, then we will | ||
| 83 | * will have to wait the sleep/awake timeout. Note, we cannot use the | ||
| 84 | * SEND_STATUS command to poll the status because that command (and most | ||
| 85 | * others) is invalid while the card sleeps. | ||
| 86 | */ | ||
| 87 | if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) | ||
| 88 | mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); | ||
| 89 | |||
| 90 | if (!sleep) | ||
| 91 | err = mmc_select_card(card); | ||
| 92 | |||
| 93 | return err; | ||
| 94 | } | ||
| 95 | |||
| 96 | int mmc_go_idle(struct mmc_host *host) | 62 | int mmc_go_idle(struct mmc_host *host) |
| 97 | { | 63 | { |
| 98 | int err; | 64 | int err; |
| @@ -431,6 +397,8 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | |||
| 431 | 397 | ||
| 432 | 398 | ||
| 433 | cmd.cmd_timeout_ms = timeout_ms; | 399 | cmd.cmd_timeout_ms = timeout_ms; |
| 400 | if (index == EXT_CSD_SANITIZE_START) | ||
| 401 | cmd.sanitize_busy = true; | ||
| 434 | 402 | ||
| 435 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); | 403 | err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); |
| 436 | if (err) | 404 | if (err) |
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 3dd8941c2980..80ae9f4e0293 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h | |||
| @@ -24,7 +24,6 @@ int mmc_send_status(struct mmc_card *card, u32 *status); | |||
| 24 | int mmc_send_cid(struct mmc_host *host, u32 *cid); | 24 | int mmc_send_cid(struct mmc_host *host, u32 *cid); |
| 25 | int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); | 25 | int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); |
| 26 | int mmc_spi_set_crc(struct mmc_host *host, int use_crc); | 26 | int mmc_spi_set_crc(struct mmc_host *host, int use_crc); |
| 27 | int mmc_card_sleepawake(struct mmc_host *host, int sleep); | ||
| 28 | int mmc_bus_test(struct mmc_card *card, u8 bus_width); | 27 | int mmc_bus_test(struct mmc_card *card, u8 bus_width); |
| 29 | int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); | 28 | int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); |
| 30 | 29 | ||
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 9e645e19cec6..176d125f5b57 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
| @@ -646,8 +646,13 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) | |||
| 646 | if (err) | 646 | if (err) |
| 647 | goto out; | 647 | goto out; |
| 648 | 648 | ||
| 649 | /* SPI mode doesn't define CMD19 */ | 649 | /* |
| 650 | if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) { | 650 | * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and |
| 651 | * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. | ||
| 652 | */ | ||
| 653 | if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning && | ||
| 654 | (card->sd_bus_speed == UHS_SDR50_BUS_SPEED || | ||
| 655 | card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) { | ||
| 651 | mmc_host_clk_hold(card->host); | 656 | mmc_host_clk_hold(card->host); |
| 652 | err = card->host->ops->execute_tuning(card->host, | 657 | err = card->host->ops->execute_tuning(card->host, |
| 653 | MMC_SEND_TUNING_BLOCK); | 658 | MMC_SEND_TUNING_BLOCK); |
| @@ -1037,14 +1042,14 @@ static void mmc_sd_detect(struct mmc_host *host) | |||
| 1037 | BUG_ON(!host); | 1042 | BUG_ON(!host); |
| 1038 | BUG_ON(!host->card); | 1043 | BUG_ON(!host->card); |
| 1039 | 1044 | ||
| 1040 | mmc_claim_host(host); | 1045 | mmc_get_card(host->card); |
| 1041 | 1046 | ||
| 1042 | /* | 1047 | /* |
| 1043 | * Just check if our card has been removed. | 1048 | * Just check if our card has been removed. |
| 1044 | */ | 1049 | */ |
| 1045 | err = _mmc_detect_card_removed(host); | 1050 | err = _mmc_detect_card_removed(host); |
| 1046 | 1051 | ||
| 1047 | mmc_release_host(host); | 1052 | mmc_put_card(host->card); |
| 1048 | 1053 | ||
| 1049 | if (err) { | 1054 | if (err) { |
| 1050 | mmc_sd_remove(host); | 1055 | mmc_sd_remove(host); |
| @@ -1070,6 +1075,8 @@ static int mmc_sd_suspend(struct mmc_host *host) | |||
| 1070 | if (!mmc_host_is_spi(host)) | 1075 | if (!mmc_host_is_spi(host)) |
| 1071 | err = mmc_deselect_cards(host); | 1076 | err = mmc_deselect_cards(host); |
| 1072 | host->card->state &= ~MMC_STATE_HIGHSPEED; | 1077 | host->card->state &= ~MMC_STATE_HIGHSPEED; |
| 1078 | if (!err) | ||
| 1079 | mmc_power_off(host); | ||
| 1073 | mmc_release_host(host); | 1080 | mmc_release_host(host); |
| 1074 | 1081 | ||
| 1075 | return err; | 1082 | return err; |
| @@ -1089,12 +1096,61 @@ static int mmc_sd_resume(struct mmc_host *host) | |||
| 1089 | BUG_ON(!host->card); | 1096 | BUG_ON(!host->card); |
| 1090 | 1097 | ||
| 1091 | mmc_claim_host(host); | 1098 | mmc_claim_host(host); |
| 1099 | mmc_power_up(host); | ||
| 1100 | mmc_select_voltage(host, host->ocr); | ||
| 1092 | err = mmc_sd_init_card(host, host->ocr, host->card); | 1101 | err = mmc_sd_init_card(host, host->ocr, host->card); |
| 1093 | mmc_release_host(host); | 1102 | mmc_release_host(host); |
| 1094 | 1103 | ||
| 1095 | return err; | 1104 | return err; |
| 1096 | } | 1105 | } |
| 1097 | 1106 | ||
| 1107 | /* | ||
| 1108 | * Callback for runtime_suspend. | ||
| 1109 | */ | ||
| 1110 | static int mmc_sd_runtime_suspend(struct mmc_host *host) | ||
| 1111 | { | ||
| 1112 | int err; | ||
| 1113 | |||
| 1114 | if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) | ||
| 1115 | return 0; | ||
| 1116 | |||
| 1117 | mmc_claim_host(host); | ||
| 1118 | |||
| 1119 | err = mmc_sd_suspend(host); | ||
| 1120 | if (err) { | ||
| 1121 | pr_err("%s: error %d doing aggessive suspend\n", | ||
| 1122 | mmc_hostname(host), err); | ||
| 1123 | goto out; | ||
| 1124 | } | ||
| 1125 | mmc_power_off(host); | ||
| 1126 | |||
| 1127 | out: | ||
| 1128 | mmc_release_host(host); | ||
| 1129 | return err; | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | /* | ||
| 1133 | * Callback for runtime_resume. | ||
| 1134 | */ | ||
| 1135 | static int mmc_sd_runtime_resume(struct mmc_host *host) | ||
| 1136 | { | ||
| 1137 | int err; | ||
| 1138 | |||
| 1139 | if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) | ||
| 1140 | return 0; | ||
| 1141 | |||
| 1142 | mmc_claim_host(host); | ||
| 1143 | |||
| 1144 | mmc_power_up(host); | ||
| 1145 | err = mmc_sd_resume(host); | ||
| 1146 | if (err) | ||
| 1147 | pr_err("%s: error %d doing aggessive resume\n", | ||
| 1148 | mmc_hostname(host), err); | ||
| 1149 | |||
| 1150 | mmc_release_host(host); | ||
| 1151 | return 0; | ||
| 1152 | } | ||
| 1153 | |||
| 1098 | static int mmc_sd_power_restore(struct mmc_host *host) | 1154 | static int mmc_sd_power_restore(struct mmc_host *host) |
| 1099 | { | 1155 | { |
| 1100 | int ret; | 1156 | int ret; |
| @@ -1114,15 +1170,19 @@ static const struct mmc_bus_ops mmc_sd_ops = { | |||
| 1114 | .resume = NULL, | 1170 | .resume = NULL, |
| 1115 | .power_restore = mmc_sd_power_restore, | 1171 | .power_restore = mmc_sd_power_restore, |
| 1116 | .alive = mmc_sd_alive, | 1172 | .alive = mmc_sd_alive, |
| 1173 | .shutdown = mmc_sd_suspend, | ||
| 1117 | }; | 1174 | }; |
| 1118 | 1175 | ||
| 1119 | static const struct mmc_bus_ops mmc_sd_ops_unsafe = { | 1176 | static const struct mmc_bus_ops mmc_sd_ops_unsafe = { |
| 1120 | .remove = mmc_sd_remove, | 1177 | .remove = mmc_sd_remove, |
| 1121 | .detect = mmc_sd_detect, | 1178 | .detect = mmc_sd_detect, |
| 1179 | .runtime_suspend = mmc_sd_runtime_suspend, | ||
| 1180 | .runtime_resume = mmc_sd_runtime_resume, | ||
| 1122 | .suspend = mmc_sd_suspend, | 1181 | .suspend = mmc_sd_suspend, |
| 1123 | .resume = mmc_sd_resume, | 1182 | .resume = mmc_sd_resume, |
| 1124 | .power_restore = mmc_sd_power_restore, | 1183 | .power_restore = mmc_sd_power_restore, |
| 1125 | .alive = mmc_sd_alive, | 1184 | .alive = mmc_sd_alive, |
| 1185 | .shutdown = mmc_sd_suspend, | ||
| 1126 | }; | 1186 | }; |
| 1127 | 1187 | ||
| 1128 | static void mmc_sd_attach_bus_ops(struct mmc_host *host) | 1188 | static void mmc_sd_attach_bus_ops(struct mmc_host *host) |
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 6889a821c1da..80d89cff7306 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
| @@ -563,10 +563,18 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card) | |||
| 563 | if (err) | 563 | if (err) |
| 564 | goto out; | 564 | goto out; |
| 565 | 565 | ||
| 566 | /* Initialize and start re-tuning timer */ | 566 | /* |
| 567 | if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) | 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. | ||
| 569 | */ | ||
| 570 | if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning && | ||
| 571 | ((card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50) || | ||
| 572 | (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104))) { | ||
| 573 | mmc_host_clk_hold(card->host); | ||
| 568 | err = card->host->ops->execute_tuning(card->host, | 574 | err = card->host->ops->execute_tuning(card->host, |
| 569 | MMC_SEND_TUNING_BLOCK); | 575 | MMC_SEND_TUNING_BLOCK); |
| 576 | mmc_host_clk_release(card->host); | ||
| 577 | } | ||
| 570 | 578 | ||
| 571 | out: | 579 | out: |
| 572 | 580 | ||
| @@ -902,11 +910,11 @@ out: | |||
| 902 | } | 910 | } |
| 903 | 911 | ||
| 904 | /* | 912 | /* |
| 905 | * SDIO suspend. We need to suspend all functions separately. | 913 | * SDIO pre_suspend. We need to suspend all functions separately. |
| 906 | * Therefore all registered functions must have drivers with suspend | 914 | * Therefore all registered functions must have drivers with suspend |
| 907 | * and resume methods. Failing that we simply remove the whole card. | 915 | * and resume methods. Failing that we simply remove the whole card. |
| 908 | */ | 916 | */ |
| 909 | static int mmc_sdio_suspend(struct mmc_host *host) | 917 | static int mmc_sdio_pre_suspend(struct mmc_host *host) |
| 910 | { | 918 | { |
| 911 | int i, err = 0; | 919 | int i, err = 0; |
| 912 | 920 | ||
| @@ -917,8 +925,26 @@ static int mmc_sdio_suspend(struct mmc_host *host) | |||
| 917 | if (!pmops || !pmops->suspend || !pmops->resume) { | 925 | if (!pmops || !pmops->suspend || !pmops->resume) { |
| 918 | /* force removal of entire card in that case */ | 926 | /* force removal of entire card in that case */ |
| 919 | err = -ENOSYS; | 927 | err = -ENOSYS; |
| 920 | } else | 928 | break; |
| 921 | err = pmops->suspend(&func->dev); | 929 | } |
| 930 | } | ||
| 931 | } | ||
| 932 | |||
| 933 | return err; | ||
| 934 | } | ||
| 935 | |||
| 936 | /* | ||
| 937 | * SDIO suspend. Suspend all functions separately. | ||
| 938 | */ | ||
| 939 | static int mmc_sdio_suspend(struct mmc_host *host) | ||
| 940 | { | ||
| 941 | int i, err = 0; | ||
| 942 | |||
| 943 | for (i = 0; i < host->card->sdio_funcs; i++) { | ||
| 944 | struct sdio_func *func = host->card->sdio_func[i]; | ||
| 945 | if (func && sdio_func_present(func) && func->dev.driver) { | ||
| 946 | const struct dev_pm_ops *pmops = func->dev.driver->pm; | ||
| 947 | err = pmops->suspend(&func->dev); | ||
| 922 | if (err) | 948 | if (err) |
| 923 | break; | 949 | break; |
| 924 | } | 950 | } |
| @@ -937,6 +963,9 @@ static int mmc_sdio_suspend(struct mmc_host *host) | |||
| 937 | mmc_release_host(host); | 963 | mmc_release_host(host); |
| 938 | } | 964 | } |
| 939 | 965 | ||
| 966 | if (!err && !mmc_card_keep_power(host)) | ||
| 967 | mmc_power_off(host); | ||
| 968 | |||
| 940 | return err; | 969 | return err; |
| 941 | } | 970 | } |
| 942 | 971 | ||
| @@ -950,6 +979,23 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
| 950 | /* Basic card reinitialization. */ | 979 | /* Basic card reinitialization. */ |
| 951 | mmc_claim_host(host); | 980 | mmc_claim_host(host); |
| 952 | 981 | ||
| 982 | /* Restore power if needed */ | ||
| 983 | if (!mmc_card_keep_power(host)) { | ||
| 984 | mmc_power_up(host); | ||
| 985 | mmc_select_voltage(host, host->ocr); | ||
| 986 | /* | ||
| 987 | * Tell runtime PM core we just powered up the card, | ||
| 988 | * since it still believes the card is powered off. | ||
| 989 | * Note that currently runtime PM is only enabled | ||
| 990 | * for SDIO cards that are MMC_CAP_POWER_OFF_CARD | ||
| 991 | */ | ||
| 992 | if (host->caps & MMC_CAP_POWER_OFF_CARD) { | ||
| 993 | pm_runtime_disable(&host->card->dev); | ||
| 994 | pm_runtime_set_active(&host->card->dev); | ||
| 995 | pm_runtime_enable(&host->card->dev); | ||
| 996 | } | ||
| 997 | } | ||
| 998 | |||
| 953 | /* No need to reinitialize powered-resumed nonremovable cards */ | 999 | /* No need to reinitialize powered-resumed nonremovable cards */ |
| 954 | if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) { | 1000 | if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) { |
| 955 | sdio_reset(host); | 1001 | sdio_reset(host); |
| @@ -987,6 +1033,7 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
| 987 | } | 1033 | } |
| 988 | } | 1034 | } |
| 989 | 1035 | ||
| 1036 | host->pm_flags &= ~MMC_PM_KEEP_POWER; | ||
| 990 | return err; | 1037 | return err; |
| 991 | } | 1038 | } |
| 992 | 1039 | ||
| @@ -1051,11 +1098,28 @@ out: | |||
| 1051 | return ret; | 1098 | return ret; |
| 1052 | } | 1099 | } |
| 1053 | 1100 | ||
| 1101 | static int mmc_sdio_runtime_suspend(struct mmc_host *host) | ||
| 1102 | { | ||
| 1103 | /* No references to the card, cut the power to it. */ | ||
| 1104 | mmc_power_off(host); | ||
| 1105 | return 0; | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | static int mmc_sdio_runtime_resume(struct mmc_host *host) | ||
| 1109 | { | ||
| 1110 | /* Restore power and re-initialize. */ | ||
| 1111 | mmc_power_up(host); | ||
| 1112 | return mmc_sdio_power_restore(host); | ||
| 1113 | } | ||
| 1114 | |||
| 1054 | static const struct mmc_bus_ops mmc_sdio_ops = { | 1115 | static const struct mmc_bus_ops mmc_sdio_ops = { |
| 1055 | .remove = mmc_sdio_remove, | 1116 | .remove = mmc_sdio_remove, |
| 1056 | .detect = mmc_sdio_detect, | 1117 | .detect = mmc_sdio_detect, |
| 1118 | .pre_suspend = mmc_sdio_pre_suspend, | ||
| 1057 | .suspend = mmc_sdio_suspend, | 1119 | .suspend = mmc_sdio_suspend, |
| 1058 | .resume = mmc_sdio_resume, | 1120 | .resume = mmc_sdio_resume, |
| 1121 | .runtime_suspend = mmc_sdio_runtime_suspend, | ||
| 1122 | .runtime_resume = mmc_sdio_runtime_resume, | ||
| 1059 | .power_restore = mmc_sdio_power_restore, | 1123 | .power_restore = mmc_sdio_power_restore, |
| 1060 | .alive = mmc_sdio_alive, | 1124 | .alive = mmc_sdio_alive, |
| 1061 | }; | 1125 | }; |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 9ab8f8dee942..8a4c066787d7 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -249,6 +249,17 @@ config MMC_SDHCI_S3C_DMA | |||
| 249 | 249 | ||
| 250 | YMMV. | 250 | YMMV. |
| 251 | 251 | ||
| 252 | config MMC_SDHCI_BCM_KONA | ||
| 253 | tristate "SDHCI support on Broadcom KONA platform" | ||
| 254 | depends on ARCH_BCM | ||
| 255 | select MMC_SDHCI_PLTFM | ||
| 256 | help | ||
| 257 | This selects the Broadcom Kona Secure Digital Host Controller | ||
| 258 | Interface(SDHCI) support. | ||
| 259 | This is used in Broadcom mobile SoCs. | ||
| 260 | |||
| 261 | If you have a controller with this interface, say Y or M here. | ||
| 262 | |||
| 252 | config MMC_SDHCI_BCM2835 | 263 | config MMC_SDHCI_BCM2835 |
| 253 | tristate "SDHCI platform support for the BCM2835 SD/MMC Controller" | 264 | tristate "SDHCI platform support for the BCM2835 SD/MMC Controller" |
| 254 | depends on ARCH_BCM2835 | 265 | depends on ARCH_BCM2835 |
| @@ -556,6 +567,14 @@ config MMC_DW_EXYNOS | |||
| 556 | Synopsys DesignWare Memory Card Interface driver. Select this option | 567 | Synopsys DesignWare Memory Card Interface driver. Select this option |
| 557 | for platforms based on Exynos4 and Exynos5 SoC's. | 568 | for platforms based on Exynos4 and Exynos5 SoC's. |
| 558 | 569 | ||
| 570 | config MMC_DW_SOCFPGA | ||
| 571 | tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface" | ||
| 572 | depends on MMC_DW | ||
| 573 | select MMC_DW_PLTFM | ||
| 574 | help | ||
| 575 | This selects support for Altera SoCFPGA specific extensions to the | ||
| 576 | Synopsys DesignWare Memory Card Interface driver. | ||
| 577 | |||
| 559 | config MMC_DW_PCI | 578 | config MMC_DW_PCI |
| 560 | tristate "Synopsys Designware MCI support on PCI bus" | 579 | tristate "Synopsys Designware MCI support on PCI bus" |
| 561 | depends on MMC_DW && PCI | 580 | depends on MMC_DW && PCI |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index cd3228075553..d422e2167e19 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
| @@ -42,6 +42,7 @@ obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o | |||
| 42 | obj-$(CONFIG_MMC_DW) += dw_mmc.o | 42 | obj-$(CONFIG_MMC_DW) += dw_mmc.o |
| 43 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o | 43 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o |
| 44 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o | 44 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o |
| 45 | obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o | ||
| 45 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o | 46 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o |
| 46 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o | 47 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o |
| 47 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o | 48 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o |
| @@ -60,6 +61,7 @@ obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o | |||
| 60 | obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o | 61 | obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o |
| 61 | obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o | 62 | obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o |
| 62 | obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o | 63 | obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o |
| 64 | obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o | ||
| 63 | obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhci-bcm2835.o | 65 | obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhci-bcm2835.o |
| 64 | 66 | ||
| 65 | ifeq ($(CONFIG_CB710_DEBUG),y) | 67 | ifeq ($(CONFIG_CB710_DEBUG),y) |
diff --git a/drivers/mmc/host/android-goldfish.c b/drivers/mmc/host/android-goldfish.c index 7780c14704c4..8b4e20a3f16c 100644 --- a/drivers/mmc/host/android-goldfish.c +++ b/drivers/mmc/host/android-goldfish.c | |||
| @@ -546,8 +546,6 @@ static int goldfish_mmc_remove(struct platform_device *pdev) | |||
| 546 | { | 546 | { |
| 547 | struct goldfish_mmc_host *host = platform_get_drvdata(pdev); | 547 | struct goldfish_mmc_host *host = platform_get_drvdata(pdev); |
| 548 | 548 | ||
| 549 | platform_set_drvdata(pdev, NULL); | ||
| 550 | |||
| 551 | BUG_ON(host == NULL); | 549 | BUG_ON(host == NULL); |
| 552 | 550 | ||
| 553 | mmc_remove_host(host->mmc); | 551 | mmc_remove_host(host->mmc); |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index aca59d93d5a9..bdb84da74952 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
| @@ -40,8 +40,6 @@ | |||
| 40 | #include <asm/io.h> | 40 | #include <asm/io.h> |
| 41 | #include <asm/unaligned.h> | 41 | #include <asm/unaligned.h> |
| 42 | 42 | ||
| 43 | #include <mach/cpu.h> | ||
| 44 | |||
| 45 | #include "atmel-mci-regs.h" | 43 | #include "atmel-mci-regs.h" |
| 46 | 44 | ||
| 47 | #define ATMCI_DATA_ERROR_FLAGS (ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE) | 45 | #define ATMCI_DATA_ERROR_FLAGS (ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE) |
| @@ -2475,8 +2473,6 @@ static int __exit atmci_remove(struct platform_device *pdev) | |||
| 2475 | struct atmel_mci *host = platform_get_drvdata(pdev); | 2473 | struct atmel_mci *host = platform_get_drvdata(pdev); |
| 2476 | unsigned int i; | 2474 | unsigned int i; |
| 2477 | 2475 | ||
| 2478 | platform_set_drvdata(pdev, NULL); | ||
| 2479 | |||
| 2480 | if (host->buffer) | 2476 | if (host->buffer) |
| 2481 | dma_free_coherent(&pdev->dev, host->buf_size, | 2477 | dma_free_coherent(&pdev->dev, host->buf_size, |
| 2482 | host->buffer, host->buf_phys_addr); | 2478 | host->buffer, host->buf_phys_addr); |
| @@ -2504,7 +2500,7 @@ static int __exit atmci_remove(struct platform_device *pdev) | |||
| 2504 | return 0; | 2500 | return 0; |
| 2505 | } | 2501 | } |
| 2506 | 2502 | ||
| 2507 | #ifdef CONFIG_PM | 2503 | #ifdef CONFIG_PM_SLEEP |
| 2508 | static int atmci_suspend(struct device *dev) | 2504 | static int atmci_suspend(struct device *dev) |
| 2509 | { | 2505 | { |
| 2510 | struct atmel_mci *host = dev_get_drvdata(dev); | 2506 | struct atmel_mci *host = dev_get_drvdata(dev); |
| @@ -2559,17 +2555,15 @@ static int atmci_resume(struct device *dev) | |||
| 2559 | 2555 | ||
| 2560 | return ret; | 2556 | return ret; |
| 2561 | } | 2557 | } |
| 2562 | static SIMPLE_DEV_PM_OPS(atmci_pm, atmci_suspend, atmci_resume); | ||
| 2563 | #define ATMCI_PM_OPS (&atmci_pm) | ||
| 2564 | #else | ||
| 2565 | #define ATMCI_PM_OPS NULL | ||
| 2566 | #endif | 2558 | #endif |
| 2567 | 2559 | ||
| 2560 | static SIMPLE_DEV_PM_OPS(atmci_pm, atmci_suspend, atmci_resume); | ||
| 2561 | |||
| 2568 | static struct platform_driver atmci_driver = { | 2562 | static struct platform_driver atmci_driver = { |
| 2569 | .remove = __exit_p(atmci_remove), | 2563 | .remove = __exit_p(atmci_remove), |
| 2570 | .driver = { | 2564 | .driver = { |
| 2571 | .name = "atmel_mci", | 2565 | .name = "atmel_mci", |
| 2572 | .pm = ATMCI_PM_OPS, | 2566 | .pm = &atmci_pm, |
| 2573 | .of_match_table = of_match_ptr(atmci_dt_ids), | 2567 | .of_match_table = of_match_ptr(atmci_dt_ids), |
| 2574 | }, | 2568 | }, |
| 2575 | }; | 2569 | }; |
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index 127a8fade4da..df9becdd2e99 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c | |||
| @@ -1149,7 +1149,6 @@ static int au1xmmc_remove(struct platform_device *pdev) | |||
| 1149 | kfree(host->ioarea); | 1149 | kfree(host->ioarea); |
| 1150 | 1150 | ||
| 1151 | mmc_free_host(host->mmc); | 1151 | mmc_free_host(host->mmc); |
| 1152 | platform_set_drvdata(pdev, NULL); | ||
| 1153 | } | 1152 | } |
| 1154 | return 0; | 1153 | return 0; |
| 1155 | } | 1154 | } |
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index fb4348c5b6ac..94fae2f1baaf 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c | |||
| @@ -621,8 +621,6 @@ static int sdh_remove(struct platform_device *pdev) | |||
| 621 | { | 621 | { |
| 622 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 622 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 623 | 623 | ||
| 624 | platform_set_drvdata(pdev, NULL); | ||
| 625 | |||
| 626 | if (mmc) { | 624 | if (mmc) { |
| 627 | struct sdh_host *host = mmc_priv(mmc); | 625 | struct sdh_host *host = mmc_priv(mmc); |
| 628 | 626 | ||
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c index 777ca2046b27..9d6e2b844404 100644 --- a/drivers/mmc/host/cb710-mmc.c +++ b/drivers/mmc/host/cb710-mmc.c | |||
| @@ -703,7 +703,7 @@ static int cb710_mmc_init(struct platform_device *pdev) | |||
| 703 | if (!mmc) | 703 | if (!mmc) |
| 704 | return -ENOMEM; | 704 | return -ENOMEM; |
| 705 | 705 | ||
| 706 | dev_set_drvdata(&pdev->dev, mmc); | 706 | platform_set_drvdata(pdev, mmc); |
| 707 | 707 | ||
| 708 | /* harmless (maybe) magic */ | 708 | /* harmless (maybe) magic */ |
| 709 | pci_read_config_dword(chip->pdev, 0x48, &val); | 709 | pci_read_config_dword(chip->pdev, 0x48, &val); |
diff --git a/drivers/mmc/host/cb710-mmc.h b/drivers/mmc/host/cb710-mmc.h index e845c776bdd7..8984ec878fc9 100644 --- a/drivers/mmc/host/cb710-mmc.h +++ b/drivers/mmc/host/cb710-mmc.h | |||
| @@ -24,7 +24,7 @@ struct cb710_mmc_reader { | |||
| 24 | 24 | ||
| 25 | static inline struct mmc_host *cb710_slot_to_mmc(struct cb710_slot *slot) | 25 | static inline struct mmc_host *cb710_slot_to_mmc(struct cb710_slot *slot) |
| 26 | { | 26 | { |
| 27 | return dev_get_drvdata(&slot->pdev.dev); | 27 | return platform_get_drvdata(&slot->pdev); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | static inline struct cb710_slot *cb710_mmc_to_slot(struct mmc_host *mmc) | 30 | static inline struct cb710_slot *cb710_mmc_to_slot(struct mmc_host *mmc) |
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 5dfb70c669dc..e9fa87df909c 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c | |||
| @@ -1407,7 +1407,6 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev) | |||
| 1407 | { | 1407 | { |
| 1408 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); | 1408 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); |
| 1409 | 1409 | ||
| 1410 | platform_set_drvdata(pdev, NULL); | ||
| 1411 | if (host) { | 1410 | if (host) { |
| 1412 | mmc_davinci_cpufreq_deregister(host); | 1411 | mmc_davinci_cpufreq_deregister(host); |
| 1413 | 1412 | ||
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index f013e7e3746b..866edef2e820 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c | |||
| @@ -31,8 +31,6 @@ | |||
| 31 | SDMMC_CLKSEL_CCLK_DRIVE(y) | \ | 31 | SDMMC_CLKSEL_CCLK_DRIVE(y) | \ |
| 32 | SDMMC_CLKSEL_CCLK_DIVIDER(z)) | 32 | SDMMC_CLKSEL_CCLK_DIVIDER(z)) |
| 33 | 33 | ||
| 34 | #define SDMMC_CMD_USE_HOLD_REG BIT(29) | ||
| 35 | |||
| 36 | #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 | 34 | #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 |
| 37 | #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 | 35 | #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 |
| 38 | 36 | ||
diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c index 083fcd29c9c6..b456b0c35231 100644 --- a/drivers/mmc/host/dw_mmc-pci.c +++ b/drivers/mmc/host/dw_mmc-pci.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include "dw_mmc.h" | 21 | #include "dw_mmc.h" |
| 22 | 22 | ||
| 23 | #define PCI_BAR_NO 2 | 23 | #define PCI_BAR_NO 2 |
| 24 | #define COMPLETE_BAR 0 | ||
| 25 | #define SYNOPSYS_DW_MCI_VENDOR_ID 0x700 | 24 | #define SYNOPSYS_DW_MCI_VENDOR_ID 0x700 |
| 26 | #define SYNOPSYS_DW_MCI_DEVICE_ID 0x1107 | 25 | #define SYNOPSYS_DW_MCI_DEVICE_ID 0x1107 |
| 27 | /* Defining the Capabilities */ | 26 | /* Defining the Capabilities */ |
| @@ -38,51 +37,37 @@ static struct dw_mci_board pci_board_data = { | |||
| 38 | }; | 37 | }; |
| 39 | 38 | ||
| 40 | static int dw_mci_pci_probe(struct pci_dev *pdev, | 39 | static int dw_mci_pci_probe(struct pci_dev *pdev, |
| 41 | const struct pci_device_id *entries) | 40 | const struct pci_device_id *entries) |
| 42 | { | 41 | { |
| 43 | struct dw_mci *host; | 42 | struct dw_mci *host; |
| 44 | int ret; | 43 | int ret; |
| 45 | 44 | ||
| 46 | ret = pci_enable_device(pdev); | 45 | ret = pcim_enable_device(pdev); |
| 47 | if (ret) | 46 | if (ret) |
| 48 | return ret; | 47 | return ret; |
| 49 | if (pci_request_regions(pdev, "dw_mmc_pci")) { | ||
| 50 | ret = -ENODEV; | ||
| 51 | goto err_disable_dev; | ||
| 52 | } | ||
| 53 | 48 | ||
| 54 | host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL); | 49 | host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL); |
| 55 | if (!host) { | 50 | if (!host) |
| 56 | ret = -ENOMEM; | 51 | return -ENOMEM; |
| 57 | goto err_release; | ||
| 58 | } | ||
| 59 | 52 | ||
| 60 | host->irq = pdev->irq; | 53 | host->irq = pdev->irq; |
| 61 | host->irq_flags = IRQF_SHARED; | 54 | host->irq_flags = IRQF_SHARED; |
| 62 | host->dev = &pdev->dev; | 55 | host->dev = &pdev->dev; |
| 63 | host->pdata = &pci_board_data; | 56 | host->pdata = &pci_board_data; |
| 64 | 57 | ||
| 65 | host->regs = pci_iomap(pdev, PCI_BAR_NO, COMPLETE_BAR); | 58 | ret = pcim_iomap_regions(pdev, 1 << PCI_BAR_NO, pci_name(pdev)); |
| 66 | if (!host->regs) { | 59 | if (ret) |
| 67 | ret = -EIO; | 60 | return ret; |
| 68 | goto err_unmap; | 61 | |
| 69 | } | 62 | host->regs = pcim_iomap_table(pdev)[0]; |
| 70 | 63 | ||
| 71 | pci_set_drvdata(pdev, host); | ||
| 72 | ret = dw_mci_probe(host); | 64 | ret = dw_mci_probe(host); |
| 73 | if (ret) | 65 | if (ret) |
| 74 | goto err_probe_failed; | 66 | return ret; |
| 75 | return ret; | 67 | |
| 76 | 68 | pci_set_drvdata(pdev, host); | |
| 77 | err_probe_failed: | 69 | |
| 78 | pci_iounmap(pdev, host->regs); | 70 | return 0; |
| 79 | err_unmap: | ||
| 80 | kfree(host); | ||
| 81 | err_release: | ||
| 82 | pci_release_regions(pdev); | ||
| 83 | err_disable_dev: | ||
| 84 | pci_disable_device(pdev); | ||
| 85 | return ret; | ||
| 86 | } | 71 | } |
| 87 | 72 | ||
| 88 | static void dw_mci_pci_remove(struct pci_dev *pdev) | 73 | static void dw_mci_pci_remove(struct pci_dev *pdev) |
| @@ -90,32 +75,23 @@ static void dw_mci_pci_remove(struct pci_dev *pdev) | |||
| 90 | struct dw_mci *host = pci_get_drvdata(pdev); | 75 | struct dw_mci *host = pci_get_drvdata(pdev); |
| 91 | 76 | ||
| 92 | dw_mci_remove(host); | 77 | dw_mci_remove(host); |
| 93 | pci_set_drvdata(pdev, NULL); | ||
| 94 | pci_release_regions(pdev); | ||
| 95 | pci_iounmap(pdev, host->regs); | ||
| 96 | kfree(host); | ||
| 97 | pci_disable_device(pdev); | ||
| 98 | } | 78 | } |
| 99 | 79 | ||
| 100 | #ifdef CONFIG_PM_SLEEP | 80 | #ifdef CONFIG_PM_SLEEP |
| 101 | static int dw_mci_pci_suspend(struct device *dev) | 81 | static int dw_mci_pci_suspend(struct device *dev) |
| 102 | { | 82 | { |
| 103 | int ret; | ||
| 104 | struct pci_dev *pdev = to_pci_dev(dev); | 83 | struct pci_dev *pdev = to_pci_dev(dev); |
| 105 | struct dw_mci *host = pci_get_drvdata(pdev); | 84 | struct dw_mci *host = pci_get_drvdata(pdev); |
| 106 | 85 | ||
| 107 | ret = dw_mci_suspend(host); | 86 | return dw_mci_suspend(host); |
| 108 | return ret; | ||
| 109 | } | 87 | } |
| 110 | 88 | ||
| 111 | static int dw_mci_pci_resume(struct device *dev) | 89 | static int dw_mci_pci_resume(struct device *dev) |
| 112 | { | 90 | { |
| 113 | int ret; | ||
| 114 | struct pci_dev *pdev = to_pci_dev(dev); | 91 | struct pci_dev *pdev = to_pci_dev(dev); |
| 115 | struct dw_mci *host = pci_get_drvdata(pdev); | 92 | struct dw_mci *host = pci_get_drvdata(pdev); |
| 116 | 93 | ||
| 117 | ret = dw_mci_resume(host); | 94 | return dw_mci_resume(host); |
| 118 | return ret; | ||
| 119 | } | 95 | } |
| 120 | #else | 96 | #else |
| 121 | #define dw_mci_pci_suspend NULL | 97 | #define dw_mci_pci_suspend NULL |
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 41c27b74b003..ee525565aa77 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c | |||
| @@ -24,8 +24,17 @@ | |||
| 24 | 24 | ||
| 25 | #include "dw_mmc.h" | 25 | #include "dw_mmc.h" |
| 26 | 26 | ||
| 27 | static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr) | ||
| 28 | { | ||
| 29 | *cmdr |= SDMMC_CMD_USE_HOLD_REG; | ||
| 30 | } | ||
| 31 | |||
| 32 | static const struct dw_mci_drv_data rockchip_drv_data = { | ||
| 33 | .prepare_command = dw_mci_rockchip_prepare_command, | ||
| 34 | }; | ||
| 35 | |||
| 27 | int dw_mci_pltfm_register(struct platform_device *pdev, | 36 | int dw_mci_pltfm_register(struct platform_device *pdev, |
| 28 | const struct dw_mci_drv_data *drv_data) | 37 | const struct dw_mci_drv_data *drv_data) |
| 29 | { | 38 | { |
| 30 | struct dw_mci *host; | 39 | struct dw_mci *host; |
| 31 | struct resource *regs; | 40 | struct resource *regs; |
| @@ -35,10 +44,6 @@ int dw_mci_pltfm_register(struct platform_device *pdev, | |||
| 35 | if (!host) | 44 | if (!host) |
| 36 | return -ENOMEM; | 45 | return -ENOMEM; |
| 37 | 46 | ||
| 38 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 39 | if (!regs) | ||
| 40 | return -ENXIO; | ||
| 41 | |||
| 42 | host->irq = platform_get_irq(pdev, 0); | 47 | host->irq = platform_get_irq(pdev, 0); |
| 43 | if (host->irq < 0) | 48 | if (host->irq < 0) |
| 44 | return host->irq; | 49 | return host->irq; |
| @@ -47,6 +52,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev, | |||
| 47 | host->dev = &pdev->dev; | 52 | host->dev = &pdev->dev; |
| 48 | host->irq_flags = 0; | 53 | host->irq_flags = 0; |
| 49 | host->pdata = pdev->dev.platform_data; | 54 | host->pdata = pdev->dev.platform_data; |
| 55 | |||
| 56 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 50 | host->regs = devm_ioremap_resource(&pdev->dev, regs); | 57 | host->regs = devm_ioremap_resource(&pdev->dev, regs); |
| 51 | if (IS_ERR(host->regs)) | 58 | if (IS_ERR(host->regs)) |
| 52 | return PTR_ERR(host->regs); | 59 | return PTR_ERR(host->regs); |
| @@ -58,52 +65,26 @@ int dw_mci_pltfm_register(struct platform_device *pdev, | |||
| 58 | } | 65 | } |
| 59 | 66 | ||
| 60 | platform_set_drvdata(pdev, host); | 67 | platform_set_drvdata(pdev, host); |
| 61 | ret = dw_mci_probe(host); | 68 | return dw_mci_probe(host); |
| 62 | return ret; | ||
| 63 | } | 69 | } |
| 64 | EXPORT_SYMBOL_GPL(dw_mci_pltfm_register); | 70 | EXPORT_SYMBOL_GPL(dw_mci_pltfm_register); |
| 65 | 71 | ||
| 66 | static int dw_mci_pltfm_probe(struct platform_device *pdev) | ||
| 67 | { | ||
| 68 | return dw_mci_pltfm_register(pdev, NULL); | ||
| 69 | } | ||
| 70 | |||
| 71 | static int dw_mci_pltfm_remove(struct platform_device *pdev) | ||
| 72 | { | ||
| 73 | struct dw_mci *host = platform_get_drvdata(pdev); | ||
| 74 | |||
| 75 | platform_set_drvdata(pdev, NULL); | ||
| 76 | dw_mci_remove(host); | ||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove); | ||
| 80 | |||
| 81 | #ifdef CONFIG_PM_SLEEP | 72 | #ifdef CONFIG_PM_SLEEP |
| 82 | /* | 73 | /* |
| 83 | * TODO: we should probably disable the clock to the card in the suspend path. | 74 | * TODO: we should probably disable the clock to the card in the suspend path. |
| 84 | */ | 75 | */ |
| 85 | static int dw_mci_pltfm_suspend(struct device *dev) | 76 | static int dw_mci_pltfm_suspend(struct device *dev) |
| 86 | { | 77 | { |
| 87 | int ret; | ||
| 88 | struct dw_mci *host = dev_get_drvdata(dev); | 78 | struct dw_mci *host = dev_get_drvdata(dev); |
| 89 | 79 | ||
| 90 | ret = dw_mci_suspend(host); | 80 | return dw_mci_suspend(host); |
| 91 | if (ret) | ||
| 92 | return ret; | ||
| 93 | |||
| 94 | return 0; | ||
| 95 | } | 81 | } |
| 96 | 82 | ||
| 97 | static int dw_mci_pltfm_resume(struct device *dev) | 83 | static int dw_mci_pltfm_resume(struct device *dev) |
| 98 | { | 84 | { |
| 99 | int ret; | ||
| 100 | struct dw_mci *host = dev_get_drvdata(dev); | 85 | struct dw_mci *host = dev_get_drvdata(dev); |
| 101 | 86 | ||
| 102 | ret = dw_mci_resume(host); | 87 | return dw_mci_resume(host); |
| 103 | if (ret) | ||
| 104 | return ret; | ||
| 105 | |||
| 106 | return 0; | ||
| 107 | } | 88 | } |
| 108 | #else | 89 | #else |
| 109 | #define dw_mci_pltfm_suspend NULL | 90 | #define dw_mci_pltfm_suspend NULL |
| @@ -115,10 +96,34 @@ EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops); | |||
| 115 | 96 | ||
| 116 | static const struct of_device_id dw_mci_pltfm_match[] = { | 97 | static const struct of_device_id dw_mci_pltfm_match[] = { |
| 117 | { .compatible = "snps,dw-mshc", }, | 98 | { .compatible = "snps,dw-mshc", }, |
| 99 | { .compatible = "rockchip,rk2928-dw-mshc", | ||
| 100 | .data = &rockchip_drv_data }, | ||
| 118 | {}, | 101 | {}, |
| 119 | }; | 102 | }; |
| 120 | MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); | 103 | MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); |
| 121 | 104 | ||
| 105 | static int dw_mci_pltfm_probe(struct platform_device *pdev) | ||
| 106 | { | ||
| 107 | const struct dw_mci_drv_data *drv_data = NULL; | ||
| 108 | const struct of_device_id *match; | ||
| 109 | |||
| 110 | if (pdev->dev.of_node) { | ||
| 111 | match = of_match_node(dw_mci_pltfm_match, pdev->dev.of_node); | ||
| 112 | drv_data = match->data; | ||
| 113 | } | ||
| 114 | |||
| 115 | return dw_mci_pltfm_register(pdev, drv_data); | ||
| 116 | } | ||
| 117 | |||
| 118 | int dw_mci_pltfm_remove(struct platform_device *pdev) | ||
| 119 | { | ||
| 120 | struct dw_mci *host = platform_get_drvdata(pdev); | ||
| 121 | |||
| 122 | dw_mci_remove(host); | ||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove); | ||
| 126 | |||
| 122 | static struct platform_driver dw_mci_pltfm_driver = { | 127 | static struct platform_driver dw_mci_pltfm_driver = { |
| 123 | .probe = dw_mci_pltfm_probe, | 128 | .probe = dw_mci_pltfm_probe, |
| 124 | .remove = dw_mci_pltfm_remove, | 129 | .remove = dw_mci_pltfm_remove, |
diff --git a/drivers/mmc/host/dw_mmc-socfpga.c b/drivers/mmc/host/dw_mmc-socfpga.c new file mode 100644 index 000000000000..14b5961a851c --- /dev/null +++ b/drivers/mmc/host/dw_mmc-socfpga.c | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | /* | ||
| 2 | * Altera SoCFPGA Specific Extensions for Synopsys DW Multimedia Card Interface | ||
| 3 | * driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2012, Samsung Electronics Co., Ltd. | ||
| 6 | * Copyright (C) 2013 Altera Corporation | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * Taken from dw_mmc-exynos.c | ||
| 14 | */ | ||
| 15 | #include <linux/clk.h> | ||
| 16 | #include <linux/mfd/syscon.h> | ||
| 17 | #include <linux/mmc/host.h> | ||
| 18 | #include <linux/mmc/dw_mmc.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/of.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/regmap.h> | ||
| 23 | |||
| 24 | #include "dw_mmc.h" | ||
| 25 | #include "dw_mmc-pltfm.h" | ||
| 26 | |||
| 27 | #define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108 | ||
| 28 | #define DRV_CLK_PHASE_SHIFT_SEL_MASK 0x7 | ||
| 29 | #define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \ | ||
| 30 | ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0)) | ||
| 31 | |||
| 32 | /* SOCFPGA implementation specific driver private data */ | ||
| 33 | struct dw_mci_socfpga_priv_data { | ||
| 34 | u8 ciu_div; /* card interface unit divisor */ | ||
| 35 | u32 hs_timing; /* bitmask for CIU clock phase shift */ | ||
| 36 | struct regmap *sysreg; /* regmap for system manager register */ | ||
| 37 | }; | ||
| 38 | |||
| 39 | static int dw_mci_socfpga_priv_init(struct dw_mci *host) | ||
| 40 | { | ||
| 41 | struct dw_mci_socfpga_priv_data *priv; | ||
| 42 | |||
| 43 | priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); | ||
| 44 | if (!priv) { | ||
| 45 | dev_err(host->dev, "mem alloc failed for private data\n"); | ||
| 46 | return -ENOMEM; | ||
| 47 | } | ||
| 48 | |||
| 49 | priv->sysreg = syscon_regmap_lookup_by_compatible("altr,sys-mgr"); | ||
| 50 | if (IS_ERR(priv->sysreg)) { | ||
| 51 | dev_err(host->dev, "regmap for altr,sys-mgr lookup failed.\n"); | ||
| 52 | return PTR_ERR(priv->sysreg); | ||
| 53 | } | ||
| 54 | host->priv = priv; | ||
| 55 | |||
| 56 | return 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | static int dw_mci_socfpga_setup_clock(struct dw_mci *host) | ||
| 60 | { | ||
| 61 | struct dw_mci_socfpga_priv_data *priv = host->priv; | ||
| 62 | |||
| 63 | clk_disable_unprepare(host->ciu_clk); | ||
| 64 | regmap_write(priv->sysreg, SYSMGR_SDMMCGRP_CTRL_OFFSET, | ||
| 65 | priv->hs_timing); | ||
| 66 | clk_prepare_enable(host->ciu_clk); | ||
| 67 | |||
| 68 | host->bus_hz /= (priv->ciu_div + 1); | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | static void dw_mci_socfpga_prepare_command(struct dw_mci *host, u32 *cmdr) | ||
| 73 | { | ||
| 74 | struct dw_mci_socfpga_priv_data *priv = host->priv; | ||
| 75 | |||
| 76 | if (priv->hs_timing & DRV_CLK_PHASE_SHIFT_SEL_MASK) | ||
| 77 | *cmdr |= SDMMC_CMD_USE_HOLD_REG; | ||
| 78 | } | ||
| 79 | |||
| 80 | static int dw_mci_socfpga_parse_dt(struct dw_mci *host) | ||
| 81 | { | ||
| 82 | struct dw_mci_socfpga_priv_data *priv = host->priv; | ||
| 83 | struct device_node *np = host->dev->of_node; | ||
| 84 | u32 timing[2]; | ||
| 85 | u32 div = 0; | ||
| 86 | int ret; | ||
| 87 | |||
| 88 | ret = of_property_read_u32(np, "altr,dw-mshc-ciu-div", &div); | ||
| 89 | if (ret) | ||
| 90 | dev_info(host->dev, "No dw-mshc-ciu-div specified, assuming 1"); | ||
| 91 | priv->ciu_div = div; | ||
| 92 | |||
| 93 | ret = of_property_read_u32_array(np, | ||
| 94 | "altr,dw-mshc-sdr-timing", timing, 2); | ||
| 95 | if (ret) | ||
| 96 | return ret; | ||
| 97 | |||
| 98 | priv->hs_timing = SYSMGR_SDMMC_CTRL_SET(timing[0], timing[1]); | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | static const struct dw_mci_drv_data socfpga_drv_data = { | ||
| 103 | .init = dw_mci_socfpga_priv_init, | ||
| 104 | .setup_clock = dw_mci_socfpga_setup_clock, | ||
| 105 | .prepare_command = dw_mci_socfpga_prepare_command, | ||
| 106 | .parse_dt = dw_mci_socfpga_parse_dt, | ||
| 107 | }; | ||
| 108 | |||
| 109 | static const struct of_device_id dw_mci_socfpga_match[] = { | ||
| 110 | { .compatible = "altr,socfpga-dw-mshc", | ||
| 111 | .data = &socfpga_drv_data, }, | ||
| 112 | {}, | ||
| 113 | }; | ||
| 114 | MODULE_DEVICE_TABLE(of, dw_mci_socfpga_match); | ||
| 115 | |||
| 116 | int dw_mci_socfpga_probe(struct platform_device *pdev) | ||
| 117 | { | ||
| 118 | const struct dw_mci_drv_data *drv_data; | ||
| 119 | const struct of_device_id *match; | ||
| 120 | |||
| 121 | match = of_match_node(dw_mci_socfpga_match, pdev->dev.of_node); | ||
| 122 | drv_data = match->data; | ||
| 123 | return dw_mci_pltfm_register(pdev, drv_data); | ||
| 124 | } | ||
| 125 | |||
| 126 | static struct platform_driver dw_mci_socfpga_pltfm_driver = { | ||
| 127 | .probe = dw_mci_socfpga_probe, | ||
| 128 | .remove = __exit_p(dw_mci_pltfm_remove), | ||
| 129 | .driver = { | ||
| 130 | .name = "dwmmc_socfpga", | ||
| 131 | .of_match_table = of_match_ptr(dw_mci_socfpga_match), | ||
| 132 | .pm = &dw_mci_pltfm_pmops, | ||
| 133 | }, | ||
| 134 | }; | ||
| 135 | |||
| 136 | module_platform_driver(dw_mci_socfpga_pltfm_driver); | ||
| 137 | |||
| 138 | MODULE_DESCRIPTION("Altera SOCFPGA Specific DW-MSHC Driver Extension"); | ||
| 139 | MODULE_LICENSE("GPL v2"); | ||
| 140 | MODULE_ALIAS("platform:dwmmc-socfpga"); | ||
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index bc3a1bc4940f..ee5f1676f14e 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | #include "dw_mmc.h" | 39 | #include "dw_mmc.h" |
| 40 | 40 | ||
| 41 | /* Common flag combinations */ | 41 | /* Common flag combinations */ |
| 42 | #define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DTO | SDMMC_INT_DCRC | \ | 42 | #define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DRTO | SDMMC_INT_DCRC | \ |
| 43 | SDMMC_INT_HTO | SDMMC_INT_SBE | \ | 43 | SDMMC_INT_HTO | SDMMC_INT_SBE | \ |
| 44 | SDMMC_INT_EBE) | 44 | SDMMC_INT_EBE) |
| 45 | #define DW_MCI_CMD_ERROR_FLAGS (SDMMC_INT_RTO | SDMMC_INT_RCRC | \ | 45 | #define DW_MCI_CMD_ERROR_FLAGS (SDMMC_INT_RTO | SDMMC_INT_RCRC | \ |
| @@ -51,6 +51,11 @@ | |||
| 51 | #define DW_MCI_DMA_THRESHOLD 16 | 51 | #define DW_MCI_DMA_THRESHOLD 16 |
| 52 | 52 | ||
| 53 | #ifdef CONFIG_MMC_DW_IDMAC | 53 | #ifdef CONFIG_MMC_DW_IDMAC |
| 54 | #define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \ | ||
| 55 | SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \ | ||
| 56 | SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \ | ||
| 57 | SDMMC_IDMAC_INT_TI) | ||
| 58 | |||
| 54 | struct idmac_desc { | 59 | struct idmac_desc { |
| 55 | u32 des0; /* Control Descriptor */ | 60 | u32 des0; /* Control Descriptor */ |
| 56 | #define IDMAC_DES0_DIC BIT(1) | 61 | #define IDMAC_DES0_DIC BIT(1) |
| @@ -433,6 +438,7 @@ static int dw_mci_idmac_init(struct dw_mci *host) | |||
| 433 | mci_writel(host, BMOD, SDMMC_IDMAC_SWRESET); | 438 | mci_writel(host, BMOD, SDMMC_IDMAC_SWRESET); |
| 434 | 439 | ||
| 435 | /* Mask out interrupts - get Tx & Rx complete only */ | 440 | /* Mask out interrupts - get Tx & Rx complete only */ |
| 441 | mci_writel(host, IDSTS, IDMAC_INT_CLR); | ||
| 436 | mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | | 442 | mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | |
| 437 | SDMMC_IDMAC_INT_TI); | 443 | SDMMC_IDMAC_INT_TI); |
| 438 | 444 | ||
| @@ -1087,7 +1093,7 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
| 1087 | status = host->data_status; | 1093 | status = host->data_status; |
| 1088 | 1094 | ||
| 1089 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | 1095 | if (status & DW_MCI_DATA_ERROR_FLAGS) { |
| 1090 | if (status & SDMMC_INT_DTO) { | 1096 | if (status & SDMMC_INT_DRTO) { |
| 1091 | data->error = -ETIMEDOUT; | 1097 | data->error = -ETIMEDOUT; |
| 1092 | } else if (status & SDMMC_INT_DCRC) { | 1098 | } else if (status & SDMMC_INT_DCRC) { |
| 1093 | data->error = -EILSEQ; | 1099 | data->error = -EILSEQ; |
| @@ -1985,19 +1991,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
| 1985 | #endif /* CONFIG_MMC_DW_IDMAC */ | 1991 | #endif /* CONFIG_MMC_DW_IDMAC */ |
| 1986 | } | 1992 | } |
| 1987 | 1993 | ||
| 1988 | host->vmmc = devm_regulator_get(mmc_dev(mmc), "vmmc"); | ||
| 1989 | if (IS_ERR(host->vmmc)) { | ||
| 1990 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); | ||
| 1991 | host->vmmc = NULL; | ||
| 1992 | } else { | ||
| 1993 | ret = regulator_enable(host->vmmc); | ||
| 1994 | if (ret) { | ||
| 1995 | dev_err(host->dev, | ||
| 1996 | "failed to enable regulator: %d\n", ret); | ||
| 1997 | goto err_setup_bus; | ||
| 1998 | } | ||
| 1999 | } | ||
| 2000 | |||
| 2001 | if (dw_mci_get_cd(mmc)) | 1994 | if (dw_mci_get_cd(mmc)) |
| 2002 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); | 1995 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); |
| 2003 | else | 1996 | else |
| @@ -2124,6 +2117,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | |||
| 2124 | struct device_node *np = dev->of_node; | 2117 | struct device_node *np = dev->of_node; |
| 2125 | const struct dw_mci_drv_data *drv_data = host->drv_data; | 2118 | const struct dw_mci_drv_data *drv_data = host->drv_data; |
| 2126 | int idx, ret; | 2119 | int idx, ret; |
| 2120 | u32 clock_frequency; | ||
| 2127 | 2121 | ||
| 2128 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 2122 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
| 2129 | if (!pdata) { | 2123 | if (!pdata) { |
| @@ -2150,6 +2144,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | |||
| 2150 | 2144 | ||
| 2151 | of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); | 2145 | of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); |
| 2152 | 2146 | ||
| 2147 | if (!of_property_read_u32(np, "clock-frequency", &clock_frequency)) | ||
| 2148 | pdata->bus_hz = clock_frequency; | ||
| 2149 | |||
| 2153 | if (drv_data && drv_data->parse_dt) { | 2150 | if (drv_data && drv_data->parse_dt) { |
| 2154 | ret = drv_data->parse_dt(host); | 2151 | ret = drv_data->parse_dt(host); |
| 2155 | if (ret) | 2152 | if (ret) |
| @@ -2207,18 +2204,23 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 2207 | host->ciu_clk = devm_clk_get(host->dev, "ciu"); | 2204 | host->ciu_clk = devm_clk_get(host->dev, "ciu"); |
| 2208 | if (IS_ERR(host->ciu_clk)) { | 2205 | if (IS_ERR(host->ciu_clk)) { |
| 2209 | dev_dbg(host->dev, "ciu clock not available\n"); | 2206 | dev_dbg(host->dev, "ciu clock not available\n"); |
| 2207 | host->bus_hz = host->pdata->bus_hz; | ||
| 2210 | } else { | 2208 | } else { |
| 2211 | ret = clk_prepare_enable(host->ciu_clk); | 2209 | ret = clk_prepare_enable(host->ciu_clk); |
| 2212 | if (ret) { | 2210 | if (ret) { |
| 2213 | dev_err(host->dev, "failed to enable ciu clock\n"); | 2211 | dev_err(host->dev, "failed to enable ciu clock\n"); |
| 2214 | goto err_clk_biu; | 2212 | goto err_clk_biu; |
| 2215 | } | 2213 | } |
| 2216 | } | ||
| 2217 | 2214 | ||
| 2218 | if (IS_ERR(host->ciu_clk)) | 2215 | if (host->pdata->bus_hz) { |
| 2219 | host->bus_hz = host->pdata->bus_hz; | 2216 | ret = clk_set_rate(host->ciu_clk, host->pdata->bus_hz); |
| 2220 | else | 2217 | if (ret) |
| 2218 | dev_warn(host->dev, | ||
| 2219 | "Unable to set bus rate to %ul\n", | ||
| 2220 | host->pdata->bus_hz); | ||
| 2221 | } | ||
| 2221 | host->bus_hz = clk_get_rate(host->ciu_clk); | 2222 | host->bus_hz = clk_get_rate(host->ciu_clk); |
| 2223 | } | ||
| 2222 | 2224 | ||
| 2223 | if (drv_data && drv_data->setup_clock) { | 2225 | if (drv_data && drv_data->setup_clock) { |
| 2224 | ret = drv_data->setup_clock(host); | 2226 | ret = drv_data->setup_clock(host); |
| @@ -2229,11 +2231,29 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 2229 | } | 2231 | } |
| 2230 | } | 2232 | } |
| 2231 | 2233 | ||
| 2234 | host->vmmc = devm_regulator_get(host->dev, "vmmc"); | ||
| 2235 | if (IS_ERR(host->vmmc)) { | ||
| 2236 | ret = PTR_ERR(host->vmmc); | ||
| 2237 | if (ret == -EPROBE_DEFER) | ||
| 2238 | goto err_clk_ciu; | ||
| 2239 | |||
| 2240 | dev_info(host->dev, "no vmmc regulator found: %d\n", ret); | ||
| 2241 | host->vmmc = NULL; | ||
| 2242 | } else { | ||
| 2243 | ret = regulator_enable(host->vmmc); | ||
| 2244 | if (ret) { | ||
| 2245 | if (ret != -EPROBE_DEFER) | ||
| 2246 | dev_err(host->dev, | ||
| 2247 | "regulator_enable fail: %d\n", ret); | ||
| 2248 | goto err_clk_ciu; | ||
| 2249 | } | ||
| 2250 | } | ||
| 2251 | |||
| 2232 | if (!host->bus_hz) { | 2252 | if (!host->bus_hz) { |
| 2233 | dev_err(host->dev, | 2253 | dev_err(host->dev, |
| 2234 | "Platform data must supply bus speed\n"); | 2254 | "Platform data must supply bus speed\n"); |
| 2235 | ret = -ENODEV; | 2255 | ret = -ENODEV; |
| 2236 | goto err_clk_ciu; | 2256 | goto err_regulator; |
| 2237 | } | 2257 | } |
| 2238 | 2258 | ||
| 2239 | host->quirks = host->pdata->quirks; | 2259 | host->quirks = host->pdata->quirks; |
| @@ -2321,8 +2341,10 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 2321 | tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); | 2341 | tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); |
| 2322 | host->card_workqueue = alloc_workqueue("dw-mci-card", | 2342 | host->card_workqueue = alloc_workqueue("dw-mci-card", |
| 2323 | WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1); | 2343 | WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1); |
| 2324 | if (!host->card_workqueue) | 2344 | if (!host->card_workqueue) { |
| 2345 | ret = -ENOMEM; | ||
| 2325 | goto err_dmaunmap; | 2346 | goto err_dmaunmap; |
| 2347 | } | ||
| 2326 | INIT_WORK(&host->card_work, dw_mci_work_routine_card); | 2348 | INIT_WORK(&host->card_work, dw_mci_work_routine_card); |
| 2327 | ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, | 2349 | ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, |
| 2328 | host->irq_flags, "dw-mci", host); | 2350 | host->irq_flags, "dw-mci", host); |
| @@ -2378,6 +2400,7 @@ err_dmaunmap: | |||
| 2378 | if (host->use_dma && host->dma_ops->exit) | 2400 | if (host->use_dma && host->dma_ops->exit) |
| 2379 | host->dma_ops->exit(host); | 2401 | host->dma_ops->exit(host); |
| 2380 | 2402 | ||
| 2403 | err_regulator: | ||
| 2381 | if (host->vmmc) | 2404 | if (host->vmmc) |
| 2382 | regulator_disable(host->vmmc); | 2405 | regulator_disable(host->vmmc); |
| 2383 | 2406 | ||
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 0b74189e7ee7..81b29941c5b9 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h | |||
| @@ -98,7 +98,7 @@ | |||
| 98 | #define SDMMC_INT_HLE BIT(12) | 98 | #define SDMMC_INT_HLE BIT(12) |
| 99 | #define SDMMC_INT_FRUN BIT(11) | 99 | #define SDMMC_INT_FRUN BIT(11) |
| 100 | #define SDMMC_INT_HTO BIT(10) | 100 | #define SDMMC_INT_HTO BIT(10) |
| 101 | #define SDMMC_INT_DTO BIT(9) | 101 | #define SDMMC_INT_DRTO BIT(9) |
| 102 | #define SDMMC_INT_RTO BIT(8) | 102 | #define SDMMC_INT_RTO BIT(8) |
| 103 | #define SDMMC_INT_DCRC BIT(7) | 103 | #define SDMMC_INT_DCRC BIT(7) |
| 104 | #define SDMMC_INT_RCRC BIT(6) | 104 | #define SDMMC_INT_RCRC BIT(6) |
| @@ -111,6 +111,7 @@ | |||
| 111 | #define SDMMC_INT_ERROR 0xbfc2 | 111 | #define SDMMC_INT_ERROR 0xbfc2 |
| 112 | /* Command register defines */ | 112 | /* Command register defines */ |
| 113 | #define SDMMC_CMD_START BIT(31) | 113 | #define SDMMC_CMD_START BIT(31) |
| 114 | #define SDMMC_CMD_USE_HOLD_REG BIT(29) | ||
| 114 | #define SDMMC_CMD_CCS_EXP BIT(23) | 115 | #define SDMMC_CMD_CCS_EXP BIT(23) |
| 115 | #define SDMMC_CMD_CEATA_RD BIT(22) | 116 | #define SDMMC_CMD_CEATA_RD BIT(22) |
| 116 | #define SDMMC_CMD_UPD_CLK BIT(21) | 117 | #define SDMMC_CMD_UPD_CLK BIT(21) |
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 2391c6b7a4bb..0308c9f1cf52 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/mmc/host.h> | 16 | #include <linux/mmc/host.h> |
| 17 | #include <linux/mmc/slot-gpio.h> | ||
| 17 | #include <linux/err.h> | 18 | #include <linux/err.h> |
| 18 | #include <linux/io.h> | 19 | #include <linux/io.h> |
| 19 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
| @@ -120,7 +121,6 @@ struct jz4740_mmc_host { | |||
| 120 | int irq; | 121 | int irq; |
| 121 | int card_detect_irq; | 122 | int card_detect_irq; |
| 122 | 123 | ||
| 123 | struct resource *mem; | ||
| 124 | void __iomem *base; | 124 | void __iomem *base; |
| 125 | struct mmc_request *req; | 125 | struct mmc_request *req; |
| 126 | struct mmc_command *cmd; | 126 | struct mmc_command *cmd; |
| @@ -231,6 +231,14 @@ static void jz4740_mmc_transfer_check_state(struct jz4740_mmc_host *host, | |||
| 231 | host->req->cmd->error = -EIO; | 231 | host->req->cmd->error = -EIO; |
| 232 | data->error = -EIO; | 232 | data->error = -EIO; |
| 233 | } | 233 | } |
| 234 | } else if (status & JZ_MMC_STATUS_READ_ERROR_MASK) { | ||
| 235 | if (status & (JZ_MMC_STATUS_TIMEOUT_READ)) { | ||
| 236 | host->req->cmd->error = -ETIMEDOUT; | ||
| 237 | data->error = -ETIMEDOUT; | ||
| 238 | } else { | ||
| 239 | host->req->cmd->error = -EIO; | ||
| 240 | data->error = -EIO; | ||
| 241 | } | ||
| 234 | } | 242 | } |
| 235 | } | 243 | } |
| 236 | 244 | ||
| @@ -560,11 +568,6 @@ static irqreturn_t jz_mmc_irq(int irq, void *devid) | |||
| 560 | if (cmd->data) | 568 | if (cmd->data) |
| 561 | cmd->data->error = -EIO; | 569 | cmd->data->error = -EIO; |
| 562 | cmd->error = -EIO; | 570 | cmd->error = -EIO; |
| 563 | } else if (status & (JZ_MMC_STATUS_CRC_READ_ERROR | | ||
| 564 | JZ_MMC_STATUS_CRC_WRITE_ERROR)) { | ||
| 565 | if (cmd->data) | ||
| 566 | cmd->data->error = -EIO; | ||
| 567 | cmd->error = -EIO; | ||
| 568 | } | 571 | } |
| 569 | 572 | ||
| 570 | jz4740_mmc_set_irq_enabled(host, irq_reg, false); | 573 | jz4740_mmc_set_irq_enabled(host, irq_reg, false); |
| @@ -626,7 +629,7 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 626 | gpio_set_value(host->pdata->gpio_power, | 629 | gpio_set_value(host->pdata->gpio_power, |
| 627 | !host->pdata->power_active_low); | 630 | !host->pdata->power_active_low); |
| 628 | host->cmdat |= JZ_MMC_CMDAT_INIT; | 631 | host->cmdat |= JZ_MMC_CMDAT_INIT; |
| 629 | clk_enable(host->clk); | 632 | clk_prepare_enable(host->clk); |
| 630 | break; | 633 | break; |
| 631 | case MMC_POWER_ON: | 634 | case MMC_POWER_ON: |
| 632 | break; | 635 | break; |
| @@ -634,7 +637,7 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 634 | if (gpio_is_valid(host->pdata->gpio_power)) | 637 | if (gpio_is_valid(host->pdata->gpio_power)) |
| 635 | gpio_set_value(host->pdata->gpio_power, | 638 | gpio_set_value(host->pdata->gpio_power, |
| 636 | host->pdata->power_active_low); | 639 | host->pdata->power_active_low); |
| 637 | clk_disable(host->clk); | 640 | clk_disable_unprepare(host->clk); |
| 638 | break; | 641 | break; |
| 639 | } | 642 | } |
| 640 | 643 | ||
| @@ -650,35 +653,6 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 650 | } | 653 | } |
| 651 | } | 654 | } |
| 652 | 655 | ||
| 653 | static int jz4740_mmc_get_ro(struct mmc_host *mmc) | ||
| 654 | { | ||
| 655 | struct jz4740_mmc_host *host = mmc_priv(mmc); | ||
| 656 | if (!gpio_is_valid(host->pdata->gpio_read_only)) | ||
| 657 | return -ENOSYS; | ||
| 658 | |||
| 659 | return gpio_get_value(host->pdata->gpio_read_only) ^ | ||
| 660 | host->pdata->read_only_active_low; | ||
| 661 | } | ||
| 662 | |||
| 663 | static int jz4740_mmc_get_cd(struct mmc_host *mmc) | ||
| 664 | { | ||
| 665 | struct jz4740_mmc_host *host = mmc_priv(mmc); | ||
| 666 | if (!gpio_is_valid(host->pdata->gpio_card_detect)) | ||
| 667 | return -ENOSYS; | ||
| 668 | |||
| 669 | return gpio_get_value(host->pdata->gpio_card_detect) ^ | ||
| 670 | host->pdata->card_detect_active_low; | ||
| 671 | } | ||
| 672 | |||
| 673 | static irqreturn_t jz4740_mmc_card_detect_irq(int irq, void *devid) | ||
| 674 | { | ||
| 675 | struct jz4740_mmc_host *host = devid; | ||
| 676 | |||
| 677 | mmc_detect_change(host->mmc, HZ / 2); | ||
| 678 | |||
| 679 | return IRQ_HANDLED; | ||
| 680 | } | ||
| 681 | |||
| 682 | static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) | 656 | static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) |
| 683 | { | 657 | { |
| 684 | struct jz4740_mmc_host *host = mmc_priv(mmc); | 658 | struct jz4740_mmc_host *host = mmc_priv(mmc); |
| @@ -688,8 +662,8 @@ static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
| 688 | static const struct mmc_host_ops jz4740_mmc_ops = { | 662 | static const struct mmc_host_ops jz4740_mmc_ops = { |
| 689 | .request = jz4740_mmc_request, | 663 | .request = jz4740_mmc_request, |
| 690 | .set_ios = jz4740_mmc_set_ios, | 664 | .set_ios = jz4740_mmc_set_ios, |
| 691 | .get_ro = jz4740_mmc_get_ro, | 665 | .get_ro = mmc_gpio_get_ro, |
| 692 | .get_cd = jz4740_mmc_get_cd, | 666 | .get_cd = mmc_gpio_get_cd, |
| 693 | .enable_sdio_irq = jz4740_mmc_enable_sdio_irq, | 667 | .enable_sdio_irq = jz4740_mmc_enable_sdio_irq, |
| 694 | }; | 668 | }; |
| 695 | 669 | ||
| @@ -724,58 +698,34 @@ static int jz4740_mmc_request_gpio(struct device *dev, int gpio, | |||
| 724 | return 0; | 698 | return 0; |
| 725 | } | 699 | } |
| 726 | 700 | ||
| 727 | static int jz4740_mmc_request_gpios(struct platform_device *pdev) | 701 | static int jz4740_mmc_request_gpios(struct mmc_host *mmc, |
| 702 | struct platform_device *pdev) | ||
| 728 | { | 703 | { |
| 729 | int ret; | ||
| 730 | struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; | 704 | struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; |
| 705 | int ret = 0; | ||
| 731 | 706 | ||
| 732 | if (!pdata) | 707 | if (!pdata) |
| 733 | return 0; | 708 | return 0; |
| 734 | 709 | ||
| 735 | ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_card_detect, | 710 | if (!pdata->card_detect_active_low) |
| 736 | "MMC detect change", false, 0); | 711 | mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; |
| 737 | if (ret) | 712 | if (!pdata->read_only_active_low) |
| 738 | goto err; | 713 | mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; |
| 739 | |||
| 740 | ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_read_only, | ||
| 741 | "MMC read only", false, 0); | ||
| 742 | if (ret) | ||
| 743 | goto err_free_gpio_card_detect; | ||
| 744 | |||
| 745 | ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, | ||
| 746 | "MMC read only", true, pdata->power_active_low); | ||
| 747 | if (ret) | ||
| 748 | goto err_free_gpio_read_only; | ||
| 749 | |||
| 750 | return 0; | ||
| 751 | |||
| 752 | err_free_gpio_read_only: | ||
| 753 | if (gpio_is_valid(pdata->gpio_read_only)) | ||
| 754 | gpio_free(pdata->gpio_read_only); | ||
| 755 | err_free_gpio_card_detect: | ||
| 756 | if (gpio_is_valid(pdata->gpio_card_detect)) | ||
| 757 | gpio_free(pdata->gpio_card_detect); | ||
| 758 | err: | ||
| 759 | return ret; | ||
| 760 | } | ||
| 761 | |||
| 762 | static int jz4740_mmc_request_cd_irq(struct platform_device *pdev, | ||
| 763 | struct jz4740_mmc_host *host) | ||
| 764 | { | ||
| 765 | struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; | ||
| 766 | 714 | ||
| 767 | if (!gpio_is_valid(pdata->gpio_card_detect)) | 715 | if (gpio_is_valid(pdata->gpio_card_detect)) { |
| 768 | return 0; | 716 | ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect); |
| 717 | if (ret) | ||
| 718 | return ret; | ||
| 719 | } | ||
| 769 | 720 | ||
| 770 | host->card_detect_irq = gpio_to_irq(pdata->gpio_card_detect); | 721 | if (gpio_is_valid(pdata->gpio_read_only)) { |
| 771 | if (host->card_detect_irq < 0) { | 722 | ret = mmc_gpio_request_ro(mmc, pdata->gpio_read_only); |
| 772 | dev_warn(&pdev->dev, "Failed to get card detect irq\n"); | 723 | if (ret) |
| 773 | return 0; | 724 | return ret; |
| 774 | } | 725 | } |
| 775 | 726 | ||
| 776 | return request_irq(host->card_detect_irq, jz4740_mmc_card_detect_irq, | 727 | return jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, |
| 777 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | 728 | "MMC read only", true, pdata->power_active_low); |
| 778 | "MMC card detect", host); | ||
| 779 | } | 729 | } |
| 780 | 730 | ||
| 781 | static void jz4740_mmc_free_gpios(struct platform_device *pdev) | 731 | static void jz4740_mmc_free_gpios(struct platform_device *pdev) |
| @@ -787,10 +737,6 @@ static void jz4740_mmc_free_gpios(struct platform_device *pdev) | |||
| 787 | 737 | ||
| 788 | if (gpio_is_valid(pdata->gpio_power)) | 738 | if (gpio_is_valid(pdata->gpio_power)) |
| 789 | gpio_free(pdata->gpio_power); | 739 | gpio_free(pdata->gpio_power); |
| 790 | if (gpio_is_valid(pdata->gpio_read_only)) | ||
| 791 | gpio_free(pdata->gpio_read_only); | ||
| 792 | if (gpio_is_valid(pdata->gpio_card_detect)) | ||
| 793 | gpio_free(pdata->gpio_card_detect); | ||
| 794 | } | 740 | } |
| 795 | 741 | ||
| 796 | static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host) | 742 | static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host) |
| @@ -808,6 +754,7 @@ static int jz4740_mmc_probe(struct platform_device* pdev) | |||
| 808 | struct mmc_host *mmc; | 754 | struct mmc_host *mmc; |
| 809 | struct jz4740_mmc_host *host; | 755 | struct jz4740_mmc_host *host; |
| 810 | struct jz4740_mmc_platform_data *pdata; | 756 | struct jz4740_mmc_platform_data *pdata; |
| 757 | struct resource *res; | ||
| 811 | 758 | ||
| 812 | pdata = pdev->dev.platform_data; | 759 | pdata = pdev->dev.platform_data; |
| 813 | 760 | ||
| @@ -827,42 +774,28 @@ static int jz4740_mmc_probe(struct platform_device* pdev) | |||
| 827 | goto err_free_host; | 774 | goto err_free_host; |
| 828 | } | 775 | } |
| 829 | 776 | ||
| 830 | host->clk = clk_get(&pdev->dev, "mmc"); | 777 | host->clk = devm_clk_get(&pdev->dev, "mmc"); |
| 831 | if (IS_ERR(host->clk)) { | 778 | if (IS_ERR(host->clk)) { |
| 832 | ret = PTR_ERR(host->clk); | 779 | ret = PTR_ERR(host->clk); |
| 833 | dev_err(&pdev->dev, "Failed to get mmc clock\n"); | 780 | dev_err(&pdev->dev, "Failed to get mmc clock\n"); |
| 834 | goto err_free_host; | 781 | goto err_free_host; |
| 835 | } | 782 | } |
| 836 | 783 | ||
| 837 | host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 784 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 838 | if (!host->mem) { | 785 | host->base = devm_ioremap_resource(&pdev->dev, res); |
| 839 | ret = -ENOENT; | ||
| 840 | dev_err(&pdev->dev, "Failed to get base platform memory\n"); | ||
| 841 | goto err_clk_put; | ||
| 842 | } | ||
| 843 | |||
| 844 | host->mem = request_mem_region(host->mem->start, | ||
| 845 | resource_size(host->mem), pdev->name); | ||
| 846 | if (!host->mem) { | ||
| 847 | ret = -EBUSY; | ||
| 848 | dev_err(&pdev->dev, "Failed to request base memory region\n"); | ||
| 849 | goto err_clk_put; | ||
| 850 | } | ||
| 851 | |||
| 852 | host->base = ioremap_nocache(host->mem->start, resource_size(host->mem)); | ||
| 853 | if (!host->base) { | 786 | if (!host->base) { |
| 854 | ret = -EBUSY; | 787 | ret = -EBUSY; |
| 855 | dev_err(&pdev->dev, "Failed to ioremap base memory\n"); | 788 | dev_err(&pdev->dev, "Failed to ioremap base memory\n"); |
| 856 | goto err_release_mem_region; | 789 | goto err_free_host; |
| 857 | } | 790 | } |
| 858 | 791 | ||
| 859 | ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); | 792 | ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); |
| 860 | if (ret) { | 793 | if (ret) { |
| 861 | dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret); | 794 | dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret); |
| 862 | goto err_iounmap; | 795 | goto err_free_host; |
| 863 | } | 796 | } |
| 864 | 797 | ||
| 865 | ret = jz4740_mmc_request_gpios(pdev); | 798 | ret = jz4740_mmc_request_gpios(mmc, pdev); |
| 866 | if (ret) | 799 | if (ret) |
| 867 | goto err_gpio_bulk_free; | 800 | goto err_gpio_bulk_free; |
| 868 | 801 | ||
| @@ -885,17 +818,11 @@ static int jz4740_mmc_probe(struct platform_device* pdev) | |||
| 885 | spin_lock_init(&host->lock); | 818 | spin_lock_init(&host->lock); |
| 886 | host->irq_mask = 0xffff; | 819 | host->irq_mask = 0xffff; |
| 887 | 820 | ||
| 888 | ret = jz4740_mmc_request_cd_irq(pdev, host); | ||
| 889 | if (ret) { | ||
| 890 | dev_err(&pdev->dev, "Failed to request card detect irq\n"); | ||
| 891 | goto err_free_gpios; | ||
| 892 | } | ||
| 893 | |||
| 894 | ret = request_threaded_irq(host->irq, jz_mmc_irq, jz_mmc_irq_worker, 0, | 821 | ret = request_threaded_irq(host->irq, jz_mmc_irq, jz_mmc_irq_worker, 0, |
| 895 | dev_name(&pdev->dev), host); | 822 | dev_name(&pdev->dev), host); |
| 896 | if (ret) { | 823 | if (ret) { |
| 897 | dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); | 824 | dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); |
| 898 | goto err_free_card_detect_irq; | 825 | goto err_free_gpios; |
| 899 | } | 826 | } |
| 900 | 827 | ||
| 901 | jz4740_mmc_reset(host); | 828 | jz4740_mmc_reset(host); |
| @@ -918,21 +845,11 @@ static int jz4740_mmc_probe(struct platform_device* pdev) | |||
| 918 | 845 | ||
| 919 | err_free_irq: | 846 | err_free_irq: |
| 920 | free_irq(host->irq, host); | 847 | free_irq(host->irq, host); |
| 921 | err_free_card_detect_irq: | ||
| 922 | if (host->card_detect_irq >= 0) | ||
| 923 | free_irq(host->card_detect_irq, host); | ||
| 924 | err_free_gpios: | 848 | err_free_gpios: |
| 925 | jz4740_mmc_free_gpios(pdev); | 849 | jz4740_mmc_free_gpios(pdev); |
| 926 | err_gpio_bulk_free: | 850 | err_gpio_bulk_free: |
| 927 | jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); | 851 | jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); |
| 928 | err_iounmap: | ||
| 929 | iounmap(host->base); | ||
| 930 | err_release_mem_region: | ||
| 931 | release_mem_region(host->mem->start, resource_size(host->mem)); | ||
| 932 | err_clk_put: | ||
| 933 | clk_put(host->clk); | ||
| 934 | err_free_host: | 852 | err_free_host: |
| 935 | platform_set_drvdata(pdev, NULL); | ||
| 936 | mmc_free_host(mmc); | 853 | mmc_free_host(mmc); |
| 937 | 854 | ||
| 938 | return ret; | 855 | return ret; |
| @@ -949,24 +866,16 @@ static int jz4740_mmc_remove(struct platform_device *pdev) | |||
| 949 | mmc_remove_host(host->mmc); | 866 | mmc_remove_host(host->mmc); |
| 950 | 867 | ||
| 951 | free_irq(host->irq, host); | 868 | free_irq(host->irq, host); |
| 952 | if (host->card_detect_irq >= 0) | ||
| 953 | free_irq(host->card_detect_irq, host); | ||
| 954 | 869 | ||
| 955 | jz4740_mmc_free_gpios(pdev); | 870 | jz4740_mmc_free_gpios(pdev); |
| 956 | jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); | 871 | jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); |
| 957 | 872 | ||
| 958 | iounmap(host->base); | ||
| 959 | release_mem_region(host->mem->start, resource_size(host->mem)); | ||
| 960 | |||
| 961 | clk_put(host->clk); | ||
| 962 | |||
| 963 | platform_set_drvdata(pdev, NULL); | ||
| 964 | mmc_free_host(host->mmc); | 873 | mmc_free_host(host->mmc); |
| 965 | 874 | ||
| 966 | return 0; | 875 | return 0; |
| 967 | } | 876 | } |
| 968 | 877 | ||
| 969 | #ifdef CONFIG_PM | 878 | #ifdef CONFIG_PM_SLEEP |
| 970 | 879 | ||
| 971 | static int jz4740_mmc_suspend(struct device *dev) | 880 | static int jz4740_mmc_suspend(struct device *dev) |
| 972 | { | 881 | { |
| @@ -990,13 +899,8 @@ static int jz4740_mmc_resume(struct device *dev) | |||
| 990 | return 0; | 899 | return 0; |
| 991 | } | 900 | } |
| 992 | 901 | ||
| 993 | const struct dev_pm_ops jz4740_mmc_pm_ops = { | 902 | static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, |
| 994 | .suspend = jz4740_mmc_suspend, | 903 | jz4740_mmc_resume); |
| 995 | .resume = jz4740_mmc_resume, | ||
| 996 | .poweroff = jz4740_mmc_suspend, | ||
| 997 | .restore = jz4740_mmc_resume, | ||
| 998 | }; | ||
| 999 | |||
| 1000 | #define JZ4740_MMC_PM_OPS (&jz4740_mmc_pm_ops) | 904 | #define JZ4740_MMC_PM_OPS (&jz4740_mmc_pm_ops) |
| 1001 | #else | 905 | #else |
| 1002 | #define JZ4740_MMC_PM_OPS NULL | 906 | #define JZ4740_MMC_PM_OPS NULL |
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 8960fc846c77..4ddd83f98658 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | #define DRIVER_NAME "mvsdio" | 36 | #define DRIVER_NAME "mvsdio" |
| 37 | 37 | ||
| 38 | static int maxfreq = MVSD_CLOCKRATE_MAX; | 38 | static int maxfreq; |
| 39 | static int nodma; | 39 | static int nodma; |
| 40 | 40 | ||
| 41 | struct mvsd_host { | 41 | struct mvsd_host { |
| @@ -685,7 +685,6 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
| 685 | const struct mbus_dram_target_info *dram; | 685 | const struct mbus_dram_target_info *dram; |
| 686 | struct resource *r; | 686 | struct resource *r; |
| 687 | int ret, irq; | 687 | int ret, irq; |
| 688 | int gpio_card_detect, gpio_write_protect; | ||
| 689 | struct pinctrl *pinctrl; | 688 | struct pinctrl *pinctrl; |
| 690 | 689 | ||
| 691 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 690 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| @@ -718,6 +717,20 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
| 718 | if (!IS_ERR(host->clk)) | 717 | if (!IS_ERR(host->clk)) |
| 719 | clk_prepare_enable(host->clk); | 718 | clk_prepare_enable(host->clk); |
| 720 | 719 | ||
| 720 | mmc->ops = &mvsd_ops; | ||
| 721 | |||
| 722 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
| 723 | |||
| 724 | mmc->f_min = DIV_ROUND_UP(host->base_clock, MVSD_BASE_DIV_MAX); | ||
| 725 | mmc->f_max = MVSD_CLOCKRATE_MAX; | ||
| 726 | |||
| 727 | mmc->max_blk_size = 2048; | ||
| 728 | mmc->max_blk_count = 65535; | ||
| 729 | |||
| 730 | mmc->max_segs = 1; | ||
| 731 | mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; | ||
| 732 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | ||
| 733 | |||
| 721 | if (np) { | 734 | if (np) { |
| 722 | if (IS_ERR(host->clk)) { | 735 | if (IS_ERR(host->clk)) { |
| 723 | dev_err(&pdev->dev, "DT platforms must have a clock associated\n"); | 736 | dev_err(&pdev->dev, "DT platforms must have a clock associated\n"); |
| @@ -726,35 +739,38 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
| 726 | } | 739 | } |
| 727 | 740 | ||
| 728 | host->base_clock = clk_get_rate(host->clk) / 2; | 741 | host->base_clock = clk_get_rate(host->clk) / 2; |
| 729 | gpio_card_detect = of_get_named_gpio(np, "cd-gpios", 0); | 742 | ret = mmc_of_parse(mmc); |
| 730 | gpio_write_protect = of_get_named_gpio(np, "wp-gpios", 0); | 743 | if (ret < 0) |
| 744 | goto out; | ||
| 731 | } else { | 745 | } else { |
| 732 | const struct mvsdio_platform_data *mvsd_data; | 746 | const struct mvsdio_platform_data *mvsd_data; |
| 747 | |||
| 733 | mvsd_data = pdev->dev.platform_data; | 748 | mvsd_data = pdev->dev.platform_data; |
| 734 | if (!mvsd_data) { | 749 | if (!mvsd_data) { |
| 735 | ret = -ENXIO; | 750 | ret = -ENXIO; |
| 736 | goto out; | 751 | goto out; |
| 737 | } | 752 | } |
| 753 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ | | ||
| 754 | MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; | ||
| 738 | host->base_clock = mvsd_data->clock / 2; | 755 | host->base_clock = mvsd_data->clock / 2; |
| 739 | gpio_card_detect = mvsd_data->gpio_card_detect ? : -EINVAL; | 756 | /* GPIO 0 regarded as invalid for backward compatibility */ |
| 740 | gpio_write_protect = mvsd_data->gpio_write_protect ? : -EINVAL; | 757 | if (mvsd_data->gpio_card_detect && |
| 741 | } | 758 | gpio_is_valid(mvsd_data->gpio_card_detect)) { |
| 742 | 759 | ret = mmc_gpio_request_cd(mmc, | |
| 743 | mmc->ops = &mvsd_ops; | 760 | mvsd_data->gpio_card_detect); |
| 744 | 761 | if (ret) | |
| 745 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 762 | goto out; |
| 746 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ | | 763 | } else { |
| 747 | MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; | 764 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
| 748 | 765 | } | |
| 749 | mmc->f_min = DIV_ROUND_UP(host->base_clock, MVSD_BASE_DIV_MAX); | ||
| 750 | mmc->f_max = maxfreq; | ||
| 751 | 766 | ||
| 752 | mmc->max_blk_size = 2048; | 767 | if (mvsd_data->gpio_write_protect && |
| 753 | mmc->max_blk_count = 65535; | 768 | gpio_is_valid(mvsd_data->gpio_write_protect)) |
| 769 | mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect); | ||
| 770 | } | ||
| 754 | 771 | ||
| 755 | mmc->max_segs = 1; | 772 | if (maxfreq) |
| 756 | mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; | 773 | mmc->f_max = maxfreq; |
| 757 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | ||
| 758 | 774 | ||
| 759 | spin_lock_init(&host->lock); | 775 | spin_lock_init(&host->lock); |
| 760 | 776 | ||
| @@ -777,15 +793,6 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
| 777 | goto out; | 793 | goto out; |
| 778 | } | 794 | } |
| 779 | 795 | ||
| 780 | if (gpio_is_valid(gpio_card_detect)) { | ||
| 781 | ret = mmc_gpio_request_cd(mmc, gpio_card_detect); | ||
| 782 | if (ret) | ||
| 783 | goto out; | ||
| 784 | } else | ||
| 785 | mmc->caps |= MMC_CAP_NEEDS_POLL; | ||
| 786 | |||
| 787 | mmc_gpio_request_ro(mmc, gpio_write_protect); | ||
| 788 | |||
| 789 | setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host); | 796 | setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host); |
| 790 | platform_set_drvdata(pdev, mmc); | 797 | platform_set_drvdata(pdev, mmc); |
| 791 | ret = mmc_add_host(mmc); | 798 | ret = mmc_add_host(mmc); |
| @@ -793,10 +800,10 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
| 793 | goto out; | 800 | goto out; |
| 794 | 801 | ||
| 795 | if (!(mmc->caps & MMC_CAP_NEEDS_POLL)) | 802 | if (!(mmc->caps & MMC_CAP_NEEDS_POLL)) |
| 796 | dev_notice(&pdev->dev, "using GPIO %d for card detection\n", | 803 | dev_notice(&pdev->dev, "using GPIO for card detection\n"); |
| 797 | gpio_card_detect); | ||
| 798 | else | 804 | else |
| 799 | dev_notice(&pdev->dev, "lacking card detect (fall back to polling)\n"); | 805 | dev_notice(&pdev->dev, |
| 806 | "lacking card detect (fall back to polling)\n"); | ||
| 800 | return 0; | 807 | return 0; |
| 801 | 808 | ||
| 802 | out: | 809 | out: |
| @@ -827,7 +834,6 @@ static int __exit mvsd_remove(struct platform_device *pdev) | |||
| 827 | clk_disable_unprepare(host->clk); | 834 | clk_disable_unprepare(host->clk); |
| 828 | mmc_free_host(mmc); | 835 | mmc_free_host(mmc); |
| 829 | 836 | ||
| 830 | platform_set_drvdata(pdev, NULL); | ||
| 831 | return 0; | 837 | return 0; |
| 832 | } | 838 | } |
| 833 | 839 | ||
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index d5036353bddc..c174c6a0d224 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
| @@ -1067,7 +1067,9 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
| 1067 | goto out_release_mem; | 1067 | goto out_release_mem; |
| 1068 | } | 1068 | } |
| 1069 | 1069 | ||
| 1070 | mmc_of_parse(mmc); | 1070 | ret = mmc_of_parse(mmc); |
| 1071 | if (ret) | ||
| 1072 | goto out_free; | ||
| 1071 | mmc->ops = &mxcmci_ops; | 1073 | mmc->ops = &mxcmci_ops; |
| 1072 | 1074 | ||
| 1073 | /* For devicetree parsing, the bus width is read from devicetree */ | 1075 | /* For devicetree parsing, the bus width is read from devicetree */ |
| @@ -1219,8 +1221,6 @@ static int mxcmci_remove(struct platform_device *pdev) | |||
| 1219 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 1221 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 1220 | struct mxcmci_host *host = mmc_priv(mmc); | 1222 | struct mxcmci_host *host = mmc_priv(mmc); |
| 1221 | 1223 | ||
| 1222 | platform_set_drvdata(pdev, NULL); | ||
| 1223 | |||
| 1224 | mmc_remove_host(mmc); | 1224 | mmc_remove_host(mmc); |
| 1225 | 1225 | ||
| 1226 | if (host->vcc) | 1226 | if (host->vcc) |
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 4278a1787d08..f38d75f46f78 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c | |||
| @@ -41,7 +41,6 @@ | |||
| 41 | #include <linux/gpio.h> | 41 | #include <linux/gpio.h> |
| 42 | #include <linux/regulator/consumer.h> | 42 | #include <linux/regulator/consumer.h> |
| 43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
| 44 | #include <linux/pinctrl/consumer.h> | ||
| 45 | #include <linux/stmp_device.h> | 44 | #include <linux/stmp_device.h> |
| 46 | #include <linux/spi/mxs-spi.h> | 45 | #include <linux/spi/mxs-spi.h> |
| 47 | 46 | ||
| @@ -580,7 +579,6 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
| 580 | struct mxs_mmc_host *host; | 579 | struct mxs_mmc_host *host; |
| 581 | struct mmc_host *mmc; | 580 | struct mmc_host *mmc; |
| 582 | struct resource *iores; | 581 | struct resource *iores; |
| 583 | struct pinctrl *pinctrl; | ||
| 584 | int ret = 0, irq_err; | 582 | int ret = 0, irq_err; |
| 585 | struct regulator *reg_vmmc; | 583 | struct regulator *reg_vmmc; |
| 586 | enum of_gpio_flags flags; | 584 | enum of_gpio_flags flags; |
| @@ -620,12 +618,6 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
| 620 | } | 618 | } |
| 621 | } | 619 | } |
| 622 | 620 | ||
| 623 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
| 624 | if (IS_ERR(pinctrl)) { | ||
| 625 | ret = PTR_ERR(pinctrl); | ||
| 626 | goto out_mmc_free; | ||
| 627 | } | ||
| 628 | |||
| 629 | ssp->clk = clk_get(&pdev->dev, NULL); | 621 | ssp->clk = clk_get(&pdev->dev, NULL); |
| 630 | if (IS_ERR(ssp->clk)) { | 622 | if (IS_ERR(ssp->clk)) { |
| 631 | ret = PTR_ERR(ssp->clk); | 623 | ret = PTR_ERR(ssp->clk); |
| @@ -639,6 +631,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
| 639 | if (!ssp->dmach) { | 631 | if (!ssp->dmach) { |
| 640 | dev_err(mmc_dev(host->mmc), | 632 | dev_err(mmc_dev(host->mmc), |
| 641 | "%s: failed to request dma\n", __func__); | 633 | "%s: failed to request dma\n", __func__); |
| 634 | ret = -ENODEV; | ||
| 642 | goto out_clk_put; | 635 | goto out_clk_put; |
| 643 | } | 636 | } |
| 644 | 637 | ||
| @@ -708,8 +701,6 @@ static int mxs_mmc_remove(struct platform_device *pdev) | |||
| 708 | 701 | ||
| 709 | mmc_remove_host(mmc); | 702 | mmc_remove_host(mmc); |
| 710 | 703 | ||
| 711 | platform_set_drvdata(pdev, NULL); | ||
| 712 | |||
| 713 | if (ssp->dmach) | 704 | if (ssp->dmach) |
| 714 | dma_release_channel(ssp->dmach); | 705 | dma_release_channel(ssp->dmach); |
| 715 | 706 | ||
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 4254975f931d..b94f38ec2a83 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
| @@ -1413,33 +1413,17 @@ static int mmc_omap_probe(struct platform_device *pdev) | |||
| 1413 | else | 1413 | else |
| 1414 | sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX; | 1414 | sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX; |
| 1415 | host->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); | 1415 | host->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); |
| 1416 | #if 0 | ||
| 1417 | if (!host->dma_tx) { | ||
| 1418 | dev_err(host->dev, "unable to obtain TX DMA engine channel %u\n", | ||
| 1419 | sig); | ||
| 1420 | goto err_dma; | ||
| 1421 | } | ||
| 1422 | #else | ||
| 1423 | if (!host->dma_tx) | 1416 | if (!host->dma_tx) |
| 1424 | dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n", | 1417 | dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n", |
| 1425 | sig); | 1418 | sig); |
| 1426 | #endif | ||
| 1427 | if (mmc_omap2()) | 1419 | if (mmc_omap2()) |
| 1428 | sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX; | 1420 | sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX; |
| 1429 | else | 1421 | else |
| 1430 | sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX; | 1422 | sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX; |
| 1431 | host->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); | 1423 | host->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); |
| 1432 | #if 0 | ||
| 1433 | if (!host->dma_rx) { | ||
| 1434 | dev_err(host->dev, "unable to obtain RX DMA engine channel %u\n", | ||
| 1435 | sig); | ||
| 1436 | goto err_dma; | ||
| 1437 | } | ||
| 1438 | #else | ||
| 1439 | if (!host->dma_rx) | 1424 | if (!host->dma_rx) |
| 1440 | dev_warn(host->dev, "unable to obtain RX DMA engine channel %u\n", | 1425 | dev_warn(host->dev, "unable to obtain RX DMA engine channel %u\n", |
| 1441 | sig); | 1426 | sig); |
| 1442 | #endif | ||
| 1443 | 1427 | ||
| 1444 | ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host); | 1428 | ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host); |
| 1445 | if (ret) | 1429 | if (ret) |
| @@ -1500,8 +1484,6 @@ static int mmc_omap_remove(struct platform_device *pdev) | |||
| 1500 | struct mmc_omap_host *host = platform_get_drvdata(pdev); | 1484 | struct mmc_omap_host *host = platform_get_drvdata(pdev); |
| 1501 | int i; | 1485 | int i; |
| 1502 | 1486 | ||
| 1503 | platform_set_drvdata(pdev, NULL); | ||
| 1504 | |||
| 1505 | BUG_ON(host == NULL); | 1487 | BUG_ON(host == NULL); |
| 1506 | 1488 | ||
| 1507 | for (i = 0; i < host->nr_slots; i++) | 1489 | for (i = 0; i < host->nr_slots; i++) |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index eccedc7d06a4..1865321465c4 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
| @@ -2047,7 +2047,6 @@ err_irq: | |||
| 2047 | } | 2047 | } |
| 2048 | err1: | 2048 | err1: |
| 2049 | iounmap(host->base); | 2049 | iounmap(host->base); |
| 2050 | platform_set_drvdata(pdev, NULL); | ||
| 2051 | mmc_free_host(mmc); | 2050 | mmc_free_host(mmc); |
| 2052 | err_alloc: | 2051 | err_alloc: |
| 2053 | omap_hsmmc_gpio_free(pdata); | 2052 | omap_hsmmc_gpio_free(pdata); |
| @@ -2093,7 +2092,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
| 2093 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2092 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 2094 | if (res) | 2093 | if (res) |
| 2095 | release_mem_region(res->start, resource_size(res)); | 2094 | release_mem_region(res->start, resource_size(res)); |
| 2096 | platform_set_drvdata(pdev, NULL); | ||
| 2097 | 2095 | ||
| 2098 | return 0; | 2096 | return 0; |
| 2099 | } | 2097 | } |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 2b2f65ada22e..847b1996ce8e 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
| @@ -834,8 +834,6 @@ static int pxamci_remove(struct platform_device *pdev) | |||
| 834 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 834 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 835 | int gpio_cd = -1, gpio_ro = -1, gpio_power = -1; | 835 | int gpio_cd = -1, gpio_ro = -1, gpio_power = -1; |
| 836 | 836 | ||
| 837 | platform_set_drvdata(pdev, NULL); | ||
| 838 | |||
| 839 | if (mmc) { | 837 | if (mmc) { |
| 840 | struct pxamci_host *host = mmc_priv(mmc); | 838 | struct pxamci_host *host = mmc_priv(mmc); |
| 841 | 839 | ||
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index ad13f4240c49..82a35b91cdbc 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c | |||
| @@ -1316,8 +1316,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) | |||
| 1316 | mmc_remove_host(mmc); | 1316 | mmc_remove_host(mmc); |
| 1317 | mmc_free_host(mmc); | 1317 | mmc_free_host(mmc); |
| 1318 | 1318 | ||
| 1319 | platform_set_drvdata(pdev, NULL); | ||
| 1320 | |||
| 1321 | dev_dbg(&(pdev->dev), | 1319 | dev_dbg(&(pdev->dev), |
| 1322 | ": Realtek PCI-E SDMMC controller has been removed\n"); | 1320 | ": Realtek PCI-E SDMMC controller has been removed\n"); |
| 1323 | 1321 | ||
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 706d9cb1a49e..cdd4ce0d7c90 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c | |||
| @@ -31,10 +31,13 @@ | |||
| 31 | #include <linux/bitops.h> | 31 | #include <linux/bitops.h> |
| 32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
| 33 | #include <linux/err.h> | 33 | #include <linux/err.h> |
| 34 | #include <linux/gpio.h> | ||
| 34 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
| 35 | #include <linux/acpi.h> | 36 | #include <linux/acpi.h> |
| 37 | #include <linux/acpi_gpio.h> | ||
| 36 | #include <linux/pm.h> | 38 | #include <linux/pm.h> |
| 37 | #include <linux/pm_runtime.h> | 39 | #include <linux/pm_runtime.h> |
| 40 | #include <linux/delay.h> | ||
| 38 | 41 | ||
| 39 | #include <linux/mmc/host.h> | 42 | #include <linux/mmc/host.h> |
| 40 | #include <linux/mmc/pm.h> | 43 | #include <linux/mmc/pm.h> |
| @@ -83,12 +86,37 @@ static int sdhci_acpi_enable_dma(struct sdhci_host *host) | |||
| 83 | return 0; | 86 | return 0; |
| 84 | } | 87 | } |
| 85 | 88 | ||
| 89 | static void sdhci_acpi_int_hw_reset(struct sdhci_host *host) | ||
| 90 | { | ||
| 91 | u8 reg; | ||
| 92 | |||
| 93 | reg = sdhci_readb(host, SDHCI_POWER_CONTROL); | ||
| 94 | reg |= 0x10; | ||
| 95 | sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); | ||
| 96 | /* For eMMC, minimum is 1us but give it 9us for good measure */ | ||
| 97 | udelay(9); | ||
| 98 | reg &= ~0x10; | ||
| 99 | sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); | ||
| 100 | /* For eMMC, minimum is 200us but give it 300us for good measure */ | ||
| 101 | usleep_range(300, 1000); | ||
| 102 | } | ||
| 103 | |||
| 86 | static const struct sdhci_ops sdhci_acpi_ops_dflt = { | 104 | static const struct sdhci_ops sdhci_acpi_ops_dflt = { |
| 87 | .enable_dma = sdhci_acpi_enable_dma, | 105 | .enable_dma = sdhci_acpi_enable_dma, |
| 88 | }; | 106 | }; |
| 89 | 107 | ||
| 108 | static const struct sdhci_ops sdhci_acpi_ops_int = { | ||
| 109 | .enable_dma = sdhci_acpi_enable_dma, | ||
| 110 | .hw_reset = sdhci_acpi_int_hw_reset, | ||
| 111 | }; | ||
| 112 | |||
| 113 | static const struct sdhci_acpi_chip sdhci_acpi_chip_int = { | ||
| 114 | .ops = &sdhci_acpi_ops_int, | ||
| 115 | }; | ||
| 116 | |||
| 90 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = { | 117 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = { |
| 91 | .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, | 118 | .chip = &sdhci_acpi_chip_int, |
| 119 | .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | MMC_CAP_HW_RESET, | ||
| 92 | .caps2 = MMC_CAP2_HC_ERASE_SZ, | 120 | .caps2 = MMC_CAP2_HC_ERASE_SZ, |
| 93 | .flags = SDHCI_ACPI_RUNTIME_PM, | 121 | .flags = SDHCI_ACPI_RUNTIME_PM, |
| 94 | }; | 122 | }; |
| @@ -101,6 +129,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { | |||
| 101 | }; | 129 | }; |
| 102 | 130 | ||
| 103 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { | 131 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { |
| 132 | .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_RUNTIME_PM, | ||
| 133 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, | ||
| 104 | }; | 134 | }; |
| 105 | 135 | ||
| 106 | struct sdhci_acpi_uid_slot { | 136 | struct sdhci_acpi_uid_slot { |
| @@ -161,6 +191,59 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(acpi_handle handle, | |||
| 161 | return slot; | 191 | return slot; |
| 162 | } | 192 | } |
| 163 | 193 | ||
| 194 | #ifdef CONFIG_PM_RUNTIME | ||
| 195 | |||
| 196 | static irqreturn_t sdhci_acpi_sd_cd(int irq, void *dev_id) | ||
| 197 | { | ||
| 198 | mmc_detect_change(dev_id, msecs_to_jiffies(200)); | ||
| 199 | return IRQ_HANDLED; | ||
| 200 | } | ||
| 201 | |||
| 202 | static int sdhci_acpi_add_own_cd(struct device *dev, int gpio, | ||
| 203 | struct mmc_host *mmc) | ||
| 204 | { | ||
| 205 | unsigned long flags; | ||
| 206 | int err, irq; | ||
| 207 | |||
| 208 | if (gpio < 0) { | ||
| 209 | err = gpio; | ||
| 210 | goto out; | ||
| 211 | } | ||
| 212 | |||
| 213 | err = devm_gpio_request_one(dev, gpio, GPIOF_DIR_IN, "sd_cd"); | ||
| 214 | if (err) | ||
| 215 | goto out; | ||
| 216 | |||
| 217 | irq = gpio_to_irq(gpio); | ||
| 218 | if (irq < 0) { | ||
| 219 | err = irq; | ||
| 220 | goto out_free; | ||
| 221 | } | ||
| 222 | |||
| 223 | flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; | ||
| 224 | err = devm_request_irq(dev, irq, sdhci_acpi_sd_cd, flags, "sd_cd", mmc); | ||
| 225 | if (err) | ||
| 226 | goto out_free; | ||
| 227 | |||
| 228 | return 0; | ||
| 229 | |||
| 230 | out_free: | ||
| 231 | devm_gpio_free(dev, gpio); | ||
| 232 | out: | ||
| 233 | dev_warn(dev, "failed to setup card detect wake up\n"); | ||
| 234 | return err; | ||
| 235 | } | ||
| 236 | |||
| 237 | #else | ||
| 238 | |||
| 239 | static int sdhci_acpi_add_own_cd(struct device *dev, int gpio, | ||
| 240 | struct mmc_host *mmc) | ||
| 241 | { | ||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | #endif | ||
| 246 | |||
| 164 | static int sdhci_acpi_probe(struct platform_device *pdev) | 247 | static int sdhci_acpi_probe(struct platform_device *pdev) |
| 165 | { | 248 | { |
| 166 | struct device *dev = &pdev->dev; | 249 | struct device *dev = &pdev->dev; |
| @@ -171,7 +254,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev) | |||
| 171 | struct resource *iomem; | 254 | struct resource *iomem; |
| 172 | resource_size_t len; | 255 | resource_size_t len; |
| 173 | const char *hid; | 256 | const char *hid; |
| 174 | int err; | 257 | int err, gpio; |
| 175 | 258 | ||
| 176 | if (acpi_bus_get_device(handle, &device)) | 259 | if (acpi_bus_get_device(handle, &device)) |
| 177 | return -ENODEV; | 260 | return -ENODEV; |
| @@ -196,6 +279,8 @@ static int sdhci_acpi_probe(struct platform_device *pdev) | |||
| 196 | if (IS_ERR(host)) | 279 | if (IS_ERR(host)) |
| 197 | return PTR_ERR(host); | 280 | return PTR_ERR(host); |
| 198 | 281 | ||
| 282 | gpio = acpi_get_gpio_by_index(dev, 0, NULL); | ||
| 283 | |||
| 199 | c = sdhci_priv(host); | 284 | c = sdhci_priv(host); |
| 200 | c->host = host; | 285 | c->host = host; |
| 201 | c->slot = sdhci_acpi_get_slot(handle, hid); | 286 | c->slot = sdhci_acpi_get_slot(handle, hid); |
| @@ -251,6 +336,11 @@ static int sdhci_acpi_probe(struct platform_device *pdev) | |||
| 251 | if (err) | 336 | if (err) |
| 252 | goto err_free; | 337 | goto err_free; |
| 253 | 338 | ||
| 339 | if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { | ||
| 340 | if (sdhci_acpi_add_own_cd(dev, gpio, host->mmc)) | ||
| 341 | c->use_runtime_pm = false; | ||
| 342 | } | ||
| 343 | |||
| 254 | if (c->use_runtime_pm) { | 344 | if (c->use_runtime_pm) { |
| 255 | pm_runtime_set_active(dev); | 345 | pm_runtime_set_active(dev); |
| 256 | pm_suspend_ignore_children(dev, 1); | 346 | pm_suspend_ignore_children(dev, 1); |
| @@ -262,7 +352,6 @@ static int sdhci_acpi_probe(struct platform_device *pdev) | |||
| 262 | return 0; | 352 | return 0; |
| 263 | 353 | ||
| 264 | err_free: | 354 | err_free: |
| 265 | platform_set_drvdata(pdev, NULL); | ||
| 266 | sdhci_free_host(c->host); | 355 | sdhci_free_host(c->host); |
| 267 | return err; | 356 | return err; |
| 268 | } | 357 | } |
| @@ -281,7 +370,6 @@ static int sdhci_acpi_remove(struct platform_device *pdev) | |||
| 281 | 370 | ||
| 282 | dead = (sdhci_readl(c->host, SDHCI_INT_STATUS) == ~0); | 371 | dead = (sdhci_readl(c->host, SDHCI_INT_STATUS) == ~0); |
| 283 | sdhci_remove_host(c->host, dead); | 372 | sdhci_remove_host(c->host, dead); |
| 284 | platform_set_drvdata(pdev, NULL); | ||
| 285 | sdhci_free_host(c->host); | 373 | sdhci_free_host(c->host); |
| 286 | 374 | ||
| 287 | return 0; | 375 | return 0; |
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c new file mode 100644 index 000000000000..87175f9817c2 --- /dev/null +++ b/drivers/mmc/host/sdhci-bcm-kona.c | |||
| @@ -0,0 +1,348 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License as | ||
| 6 | * published by the Free Software Foundation version 2. | ||
| 7 | * | ||
| 8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 9 | * kind, whether express or implied; without even the implied warranty | ||
| 10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/highmem.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/mmc/host.h> | ||
| 20 | #include <linux/io.h> | ||
| 21 | #include <linux/gpio.h> | ||
| 22 | #include <linux/clk.h> | ||
| 23 | #include <linux/regulator/consumer.h> | ||
| 24 | #include <linux/of.h> | ||
| 25 | #include <linux/of_device.h> | ||
| 26 | #include <linux/of_gpio.h> | ||
| 27 | #include <linux/version.h> | ||
| 28 | #include <linux/mmc/slot-gpio.h> | ||
| 29 | |||
| 30 | #include "sdhci-pltfm.h" | ||
| 31 | #include "sdhci.h" | ||
| 32 | |||
| 33 | #define SDHCI_SOFT_RESET 0x01000000 | ||
| 34 | #define KONA_SDHOST_CORECTRL 0x8000 | ||
| 35 | #define KONA_SDHOST_CD_PINCTRL 0x00000008 | ||
| 36 | #define KONA_SDHOST_STOP_HCLK 0x00000004 | ||
| 37 | #define KONA_SDHOST_RESET 0x00000002 | ||
| 38 | #define KONA_SDHOST_EN 0x00000001 | ||
| 39 | |||
| 40 | #define KONA_SDHOST_CORESTAT 0x8004 | ||
| 41 | #define KONA_SDHOST_WP 0x00000002 | ||
| 42 | #define KONA_SDHOST_CD_SW 0x00000001 | ||
| 43 | |||
| 44 | #define KONA_SDHOST_COREIMR 0x8008 | ||
| 45 | #define KONA_SDHOST_IP 0x00000001 | ||
| 46 | |||
| 47 | #define KONA_SDHOST_COREISR 0x800C | ||
| 48 | #define KONA_SDHOST_COREIMSR 0x8010 | ||
| 49 | #define KONA_SDHOST_COREDBG1 0x8014 | ||
| 50 | #define KONA_SDHOST_COREGPO_MASK 0x8018 | ||
| 51 | |||
| 52 | #define SD_DETECT_GPIO_DEBOUNCE_128MS 128 | ||
| 53 | |||
| 54 | #define KONA_MMC_AUTOSUSPEND_DELAY (50) | ||
| 55 | |||
| 56 | struct sdhci_bcm_kona_dev { | ||
| 57 | struct mutex write_lock; /* protect back to back writes */ | ||
| 58 | }; | ||
| 59 | |||
| 60 | |||
| 61 | static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host) | ||
| 62 | { | ||
| 63 | unsigned int val; | ||
| 64 | unsigned long timeout; | ||
| 65 | |||
| 66 | /* This timeout should be sufficent for core to reset */ | ||
| 67 | timeout = jiffies + msecs_to_jiffies(100); | ||
| 68 | |||
| 69 | /* reset the host using the top level reset */ | ||
| 70 | val = sdhci_readl(host, KONA_SDHOST_CORECTRL); | ||
| 71 | val |= KONA_SDHOST_RESET; | ||
| 72 | sdhci_writel(host, val, KONA_SDHOST_CORECTRL); | ||
| 73 | |||
| 74 | while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) { | ||
| 75 | if (time_is_before_jiffies(timeout)) { | ||
| 76 | pr_err("Error: sd host is stuck in reset!!!\n"); | ||
| 77 | return -EFAULT; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | /* bring the host out of reset */ | ||
| 82 | val = sdhci_readl(host, KONA_SDHOST_CORECTRL); | ||
| 83 | val &= ~KONA_SDHOST_RESET; | ||
| 84 | |||
| 85 | /* | ||
| 86 | * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS) | ||
| 87 | * Back-to-Back writes to same register needs delay when SD bus clock | ||
| 88 | * is very low w.r.t AHB clock, mainly during boot-time and during card | ||
| 89 | * insert-removal. | ||
| 90 | */ | ||
| 91 | usleep_range(1000, 5000); | ||
| 92 | sdhci_writel(host, val, KONA_SDHOST_CORECTRL); | ||
| 93 | |||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | static void sdhci_bcm_kona_sd_init(struct sdhci_host *host) | ||
| 98 | { | ||
| 99 | unsigned int val; | ||
| 100 | |||
| 101 | /* enable the interrupt from the IP core */ | ||
| 102 | val = sdhci_readl(host, KONA_SDHOST_COREIMR); | ||
| 103 | val |= KONA_SDHOST_IP; | ||
| 104 | sdhci_writel(host, val, KONA_SDHOST_COREIMR); | ||
| 105 | |||
| 106 | /* Enable the AHB clock gating module to the host */ | ||
| 107 | val = sdhci_readl(host, KONA_SDHOST_CORECTRL); | ||
| 108 | val |= KONA_SDHOST_EN; | ||
| 109 | |||
| 110 | /* | ||
| 111 | * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS) | ||
| 112 | * Back-to-Back writes to same register needs delay when SD bus clock | ||
| 113 | * is very low w.r.t AHB clock, mainly during boot-time and during card | ||
| 114 | * insert-removal. | ||
| 115 | */ | ||
| 116 | usleep_range(1000, 5000); | ||
| 117 | sdhci_writel(host, val, KONA_SDHOST_CORECTRL); | ||
| 118 | } | ||
| 119 | |||
| 120 | /* | ||
| 121 | * Software emulation of the SD card insertion/removal. Set insert=1 for insert | ||
| 122 | * and insert=0 for removal. The card detection is done by GPIO. For Broadcom | ||
| 123 | * IP to function properly the bit 0 of CORESTAT register needs to be set/reset | ||
| 124 | * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet. | ||
| 125 | */ | ||
| 126 | static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert) | ||
| 127 | { | ||
| 128 | struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); | ||
| 129 | struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv); | ||
| 130 | u32 val; | ||
| 131 | |||
| 132 | /* | ||
| 133 | * Back-to-Back register write needs a delay of min 10uS. | ||
| 134 | * Back-to-Back writes to same register needs delay when SD bus clock | ||
| 135 | * is very low w.r.t AHB clock, mainly during boot-time and during card | ||
| 136 | * insert-removal. | ||
| 137 | * We keep 20uS | ||
| 138 | */ | ||
| 139 | mutex_lock(&kona_dev->write_lock); | ||
| 140 | udelay(20); | ||
| 141 | val = sdhci_readl(host, KONA_SDHOST_CORESTAT); | ||
| 142 | |||
| 143 | if (insert) { | ||
| 144 | int ret; | ||
| 145 | |||
| 146 | ret = mmc_gpio_get_ro(host->mmc); | ||
| 147 | if (ret >= 0) | ||
| 148 | val = (val & ~KONA_SDHOST_WP) | | ||
| 149 | ((ret) ? KONA_SDHOST_WP : 0); | ||
| 150 | |||
| 151 | val |= KONA_SDHOST_CD_SW; | ||
| 152 | sdhci_writel(host, val, KONA_SDHOST_CORESTAT); | ||
| 153 | } else { | ||
| 154 | val &= ~KONA_SDHOST_CD_SW; | ||
| 155 | sdhci_writel(host, val, KONA_SDHOST_CORESTAT); | ||
| 156 | } | ||
| 157 | mutex_unlock(&kona_dev->write_lock); | ||
| 158 | |||
| 159 | return 0; | ||
| 160 | } | ||
| 161 | |||
| 162 | /* | ||
| 163 | * SD card interrupt event callback | ||
| 164 | */ | ||
| 165 | void sdhci_bcm_kona_card_event(struct sdhci_host *host) | ||
| 166 | { | ||
| 167 | if (mmc_gpio_get_cd(host->mmc) > 0) { | ||
| 168 | dev_dbg(mmc_dev(host->mmc), | ||
| 169 | "card inserted\n"); | ||
| 170 | sdhci_bcm_kona_sd_card_emulate(host, 1); | ||
| 171 | } else { | ||
| 172 | dev_dbg(mmc_dev(host->mmc), | ||
| 173 | "card removed\n"); | ||
| 174 | sdhci_bcm_kona_sd_card_emulate(host, 0); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | /* | ||
| 179 | * Get the base clock. Use central clock source for now. Not sure if different | ||
| 180 | * clock speed to each dev is allowed | ||
| 181 | */ | ||
| 182 | static unsigned int sdhci_bcm_kona_get_max_clk(struct sdhci_host *host) | ||
| 183 | { | ||
| 184 | struct sdhci_bcm_kona_dev *kona_dev; | ||
| 185 | struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); | ||
| 186 | kona_dev = sdhci_pltfm_priv(pltfm_priv); | ||
| 187 | |||
| 188 | return host->mmc->f_max; | ||
| 189 | } | ||
| 190 | |||
| 191 | static unsigned int sdhci_bcm_kona_get_timeout_clock(struct sdhci_host *host) | ||
| 192 | { | ||
| 193 | return sdhci_bcm_kona_get_max_clk(host); | ||
| 194 | } | ||
| 195 | |||
| 196 | static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host, | ||
| 197 | u8 power_mode) | ||
| 198 | { | ||
| 199 | /* | ||
| 200 | * JEDEC and SD spec specify supplying 74 continuous clocks to | ||
| 201 | * device after power up. With minimum bus (100KHz) that | ||
| 202 | * that translates to 740us | ||
| 203 | */ | ||
| 204 | if (power_mode != MMC_POWER_OFF) | ||
| 205 | udelay(740); | ||
| 206 | } | ||
| 207 | |||
| 208 | static struct sdhci_ops sdhci_bcm_kona_ops = { | ||
| 209 | .get_max_clock = sdhci_bcm_kona_get_max_clk, | ||
| 210 | .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock, | ||
| 211 | .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, | ||
| 212 | .card_event = sdhci_bcm_kona_card_event, | ||
| 213 | }; | ||
| 214 | |||
| 215 | static struct sdhci_pltfm_data sdhci_pltfm_data_kona = { | ||
| 216 | .ops = &sdhci_bcm_kona_ops, | ||
| 217 | .quirks = SDHCI_QUIRK_NO_CARD_NO_RESET | | ||
| 218 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_32BIT_DMA_ADDR | | ||
| 219 | SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE | | ||
| 220 | SDHCI_QUIRK_FORCE_BLK_SZ_2048 | | ||
| 221 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, | ||
| 222 | }; | ||
| 223 | |||
| 224 | static const struct of_device_id sdhci_bcm_kona_of_match[] __initdata = { | ||
| 225 | { .compatible = "bcm,kona-sdhci"}, | ||
| 226 | {} | ||
| 227 | }; | ||
| 228 | MODULE_DEVICE_TABLE(of, sdhci_bcm_kona_of_match); | ||
| 229 | |||
| 230 | static int __init sdhci_bcm_kona_probe(struct platform_device *pdev) | ||
| 231 | { | ||
| 232 | struct sdhci_bcm_kona_dev *kona_dev = NULL; | ||
| 233 | struct sdhci_pltfm_host *pltfm_priv; | ||
| 234 | struct device *dev = &pdev->dev; | ||
| 235 | struct sdhci_host *host; | ||
| 236 | int ret; | ||
| 237 | |||
| 238 | ret = 0; | ||
| 239 | |||
| 240 | host = sdhci_pltfm_init(pdev, &sdhci_pltfm_data_kona, | ||
| 241 | sizeof(*kona_dev)); | ||
| 242 | if (IS_ERR(host)) | ||
| 243 | return PTR_ERR(host); | ||
| 244 | |||
| 245 | dev_dbg(dev, "%s: inited. IOADDR=%p\n", __func__, host->ioaddr); | ||
| 246 | |||
| 247 | pltfm_priv = sdhci_priv(host); | ||
| 248 | |||
| 249 | kona_dev = sdhci_pltfm_priv(pltfm_priv); | ||
| 250 | mutex_init(&kona_dev->write_lock); | ||
| 251 | |||
| 252 | mmc_of_parse(host->mmc); | ||
| 253 | |||
| 254 | if (!host->mmc->f_max) { | ||
| 255 | dev_err(&pdev->dev, "Missing max-freq for SDHCI cfg\n"); | ||
| 256 | ret = -ENXIO; | ||
| 257 | goto err_pltfm_free; | ||
| 258 | } | ||
| 259 | |||
| 260 | dev_dbg(dev, "non-removable=%c\n", | ||
| 261 | (host->mmc->caps & MMC_CAP_NONREMOVABLE) ? 'Y' : 'N'); | ||
| 262 | dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n", | ||
| 263 | (mmc_gpio_get_cd(host->mmc) != -ENOSYS) ? 'Y' : 'N', | ||
| 264 | (mmc_gpio_get_ro(host->mmc) != -ENOSYS) ? 'Y' : 'N'); | ||
| 265 | |||
| 266 | if (host->mmc->caps | MMC_CAP_NONREMOVABLE) | ||
| 267 | host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; | ||
| 268 | |||
| 269 | dev_dbg(dev, "is_8bit=%c\n", | ||
| 270 | (host->mmc->caps | MMC_CAP_8_BIT_DATA) ? 'Y' : 'N'); | ||
| 271 | |||
| 272 | ret = sdhci_bcm_kona_sd_reset(host); | ||
| 273 | if (ret) | ||
| 274 | goto err_pltfm_free; | ||
| 275 | |||
| 276 | sdhci_bcm_kona_sd_init(host); | ||
| 277 | |||
| 278 | ret = sdhci_add_host(host); | ||
| 279 | if (ret) { | ||
| 280 | dev_err(dev, "Failed sdhci_add_host\n"); | ||
| 281 | goto err_reset; | ||
| 282 | } | ||
| 283 | |||
| 284 | /* if device is eMMC, emulate card insert right here */ | ||
| 285 | if (host->mmc->caps | MMC_CAP_NONREMOVABLE) { | ||
| 286 | ret = sdhci_bcm_kona_sd_card_emulate(host, 1); | ||
| 287 | if (ret) { | ||
| 288 | dev_err(dev, | ||
| 289 | "unable to emulate card insertion\n"); | ||
| 290 | goto err_remove_host; | ||
| 291 | } | ||
| 292 | } | ||
| 293 | /* | ||
| 294 | * Since the card detection GPIO interrupt is configured to be | ||
| 295 | * edge sensitive, check the initial GPIO value here, emulate | ||
| 296 | * only if the card is present | ||
| 297 | */ | ||
| 298 | if (mmc_gpio_get_cd(host->mmc) > 0) | ||
| 299 | sdhci_bcm_kona_sd_card_emulate(host, 1); | ||
| 300 | |||
| 301 | dev_dbg(dev, "initialized properly\n"); | ||
| 302 | return 0; | ||
| 303 | |||
| 304 | err_remove_host: | ||
| 305 | sdhci_remove_host(host, 0); | ||
| 306 | |||
| 307 | err_reset: | ||
| 308 | sdhci_bcm_kona_sd_reset(host); | ||
| 309 | |||
| 310 | err_pltfm_free: | ||
| 311 | sdhci_pltfm_free(pdev); | ||
| 312 | |||
| 313 | dev_err(dev, "Probing of sdhci-pltfm failed: %d\n", ret); | ||
| 314 | return ret; | ||
| 315 | } | ||
| 316 | |||
| 317 | static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev) | ||
| 318 | { | ||
| 319 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
| 320 | int dead; | ||
| 321 | u32 scratch; | ||
| 322 | |||
| 323 | dead = 0; | ||
| 324 | scratch = readl(host->ioaddr + SDHCI_INT_STATUS); | ||
| 325 | if (scratch == (u32)-1) | ||
| 326 | dead = 1; | ||
| 327 | sdhci_remove_host(host, dead); | ||
| 328 | |||
| 329 | sdhci_free_host(host); | ||
| 330 | |||
| 331 | return 0; | ||
| 332 | } | ||
| 333 | |||
| 334 | static struct platform_driver sdhci_bcm_kona_driver = { | ||
| 335 | .driver = { | ||
| 336 | .name = "sdhci-kona", | ||
| 337 | .owner = THIS_MODULE, | ||
| 338 | .pm = SDHCI_PLTFM_PMOPS, | ||
| 339 | .of_match_table = of_match_ptr(sdhci_bcm_kona_of_match), | ||
| 340 | }, | ||
| 341 | .probe = sdhci_bcm_kona_probe, | ||
| 342 | .remove = __exit_p(sdhci_bcm_kona_remove), | ||
| 343 | }; | ||
| 344 | module_platform_driver(sdhci_bcm_kona_driver); | ||
| 345 | |||
| 346 | MODULE_DESCRIPTION("SDHCI driver for Broadcom Kona platform"); | ||
| 347 | MODULE_AUTHOR("Broadcom"); | ||
| 348 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c index d49bc958c8ba..0584a1c788b8 100644 --- a/drivers/mmc/host/sdhci-bcm2835.c +++ b/drivers/mmc/host/sdhci-bcm2835.c | |||
| @@ -148,7 +148,7 @@ static int bcm2835_sdhci_probe(struct platform_device *pdev) | |||
| 148 | struct sdhci_pltfm_host *pltfm_host; | 148 | struct sdhci_pltfm_host *pltfm_host; |
| 149 | int ret; | 149 | int ret; |
| 150 | 150 | ||
| 151 | host = sdhci_pltfm_init(pdev, &bcm2835_sdhci_pdata); | 151 | host = sdhci_pltfm_init(pdev, &bcm2835_sdhci_pdata, 0); |
| 152 | if (IS_ERR(host)) | 152 | if (IS_ERR(host)) |
| 153 | return PTR_ERR(host); | 153 | return PTR_ERR(host); |
| 154 | 154 | ||
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c index 8ebb6b650f3f..f2cc26633cb2 100644 --- a/drivers/mmc/host/sdhci-cns3xxx.c +++ b/drivers/mmc/host/sdhci-cns3xxx.c | |||
| @@ -96,7 +96,7 @@ static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = { | |||
| 96 | 96 | ||
| 97 | static int sdhci_cns3xxx_probe(struct platform_device *pdev) | 97 | static int sdhci_cns3xxx_probe(struct platform_device *pdev) |
| 98 | { | 98 | { |
| 99 | return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata); | 99 | return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata, 0); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static int sdhci_cns3xxx_remove(struct platform_device *pdev) | 102 | static int sdhci_cns3xxx_remove(struct platform_device *pdev) |
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 15e7803040f1..8424839660f8 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c | |||
| @@ -130,7 +130,7 @@ static int sdhci_dove_probe(struct platform_device *pdev) | |||
| 130 | gpio_direction_input(priv->gpio_cd); | 130 | gpio_direction_input(priv->gpio_cd); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata); | 133 | host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0); |
| 134 | if (IS_ERR(host)) { | 134 | if (IS_ERR(host)) { |
| 135 | ret = PTR_ERR(host); | 135 | ret = PTR_ERR(host); |
| 136 | goto err_sdhci_pltfm_init; | 136 | goto err_sdhci_pltfm_init; |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index d5f0d59e1310..1dd5ba858754 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
| @@ -384,6 +384,20 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) | |||
| 384 | } | 384 | } |
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) | ||
| 388 | { | ||
| 389 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 390 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
| 391 | struct esdhc_platform_data *boarddata = &imx_data->boarddata; | ||
| 392 | |||
| 393 | u32 f_host = clk_get_rate(pltfm_host->clk); | ||
| 394 | |||
| 395 | if (boarddata->f_max && (boarddata->f_max < f_host)) | ||
| 396 | return boarddata->f_max; | ||
| 397 | else | ||
| 398 | return f_host; | ||
| 399 | } | ||
| 400 | |||
| 387 | static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) | 401 | static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) |
| 388 | { | 402 | { |
| 389 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 403 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| @@ -391,6 +405,14 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) | |||
| 391 | return clk_get_rate(pltfm_host->clk) / 256 / 16; | 405 | return clk_get_rate(pltfm_host->clk) / 256 / 16; |
| 392 | } | 406 | } |
| 393 | 407 | ||
| 408 | static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, | ||
| 409 | unsigned int clock) | ||
| 410 | { | ||
| 411 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 412 | |||
| 413 | esdhc_set_clock(host, clock, clk_get_rate(pltfm_host->clk)); | ||
| 414 | } | ||
| 415 | |||
| 394 | static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) | 416 | static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) |
| 395 | { | 417 | { |
| 396 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 418 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| @@ -438,8 +460,8 @@ static const struct sdhci_ops sdhci_esdhc_ops = { | |||
| 438 | .write_l = esdhc_writel_le, | 460 | .write_l = esdhc_writel_le, |
| 439 | .write_w = esdhc_writew_le, | 461 | .write_w = esdhc_writew_le, |
| 440 | .write_b = esdhc_writeb_le, | 462 | .write_b = esdhc_writeb_le, |
| 441 | .set_clock = esdhc_set_clock, | 463 | .set_clock = esdhc_pltfm_set_clock, |
| 442 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, | 464 | .get_max_clock = esdhc_pltfm_get_max_clock, |
| 443 | .get_min_clock = esdhc_pltfm_get_min_clock, | 465 | .get_min_clock = esdhc_pltfm_get_min_clock, |
| 444 | .get_ro = esdhc_pltfm_get_ro, | 466 | .get_ro = esdhc_pltfm_get_ro, |
| 445 | .platform_bus_width = esdhc_pltfm_bus_width, | 467 | .platform_bus_width = esdhc_pltfm_bus_width, |
| @@ -482,6 +504,8 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, | |||
| 482 | 504 | ||
| 483 | of_property_read_u32(np, "bus-width", &boarddata->max_bus_width); | 505 | of_property_read_u32(np, "bus-width", &boarddata->max_bus_width); |
| 484 | 506 | ||
| 507 | of_property_read_u32(np, "max-frequency", &boarddata->f_max); | ||
| 508 | |||
| 485 | return 0; | 509 | return 0; |
| 486 | } | 510 | } |
| 487 | #else | 511 | #else |
| @@ -503,7 +527,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
| 503 | int err; | 527 | int err; |
| 504 | struct pltfm_imx_data *imx_data; | 528 | struct pltfm_imx_data *imx_data; |
| 505 | 529 | ||
| 506 | host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata); | 530 | host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata, 0); |
| 507 | if (IS_ERR(host)) | 531 | if (IS_ERR(host)) |
| 508 | return PTR_ERR(host); | 532 | return PTR_ERR(host); |
| 509 | 533 | ||
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index d25f9ab9a54d..a2a06420e463 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h | |||
| @@ -36,13 +36,21 @@ | |||
| 36 | /* pltfm-specific */ | 36 | /* pltfm-specific */ |
| 37 | #define ESDHC_HOST_CONTROL_LE 0x20 | 37 | #define ESDHC_HOST_CONTROL_LE 0x20 |
| 38 | 38 | ||
| 39 | /* | ||
| 40 | * P2020 interpretation of the SDHCI_HOST_CONTROL register | ||
| 41 | */ | ||
| 42 | #define ESDHC_CTRL_4BITBUS (0x1 << 1) | ||
| 43 | #define ESDHC_CTRL_8BITBUS (0x2 << 1) | ||
| 44 | #define ESDHC_CTRL_BUSWIDTH_MASK (0x3 << 1) | ||
| 45 | |||
| 39 | /* OF-specific */ | 46 | /* OF-specific */ |
| 40 | #define ESDHC_DMA_SYSCTL 0x40c | 47 | #define ESDHC_DMA_SYSCTL 0x40c |
| 41 | #define ESDHC_DMA_SNOOP 0x00000040 | 48 | #define ESDHC_DMA_SNOOP 0x00000040 |
| 42 | 49 | ||
| 43 | #define ESDHC_HOST_CONTROL_RES 0x05 | 50 | #define ESDHC_HOST_CONTROL_RES 0x05 |
| 44 | 51 | ||
| 45 | static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) | 52 | static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock, |
| 53 | unsigned int host_clock) | ||
| 46 | { | 54 | { |
| 47 | int pre_div = 2; | 55 | int pre_div = 2; |
| 48 | int div = 1; | 56 | int div = 1; |
| @@ -56,14 +64,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 56 | | ESDHC_CLOCK_MASK); | 64 | | ESDHC_CLOCK_MASK); |
| 57 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | 65 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); |
| 58 | 66 | ||
| 59 | while (host->max_clk / pre_div / 16 > clock && pre_div < 256) | 67 | while (host_clock / pre_div / 16 > clock && pre_div < 256) |
| 60 | pre_div *= 2; | 68 | pre_div *= 2; |
| 61 | 69 | ||
| 62 | while (host->max_clk / pre_div / div > clock && div < 16) | 70 | while (host_clock / pre_div / div > clock && div < 16) |
| 63 | div++; | 71 | div++; |
| 64 | 72 | ||
| 65 | dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", | 73 | dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", |
| 66 | clock, host->max_clk / pre_div / div); | 74 | clock, host_clock / pre_div / div); |
| 67 | 75 | ||
| 68 | pre_div >>= 1; | 76 | pre_div >>= 1; |
| 69 | div--; | 77 | div--; |
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 5e68adc2461e..15039e2d1c12 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | * your option) any later version. | 13 | * your option) any later version. |
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/err.h> | ||
| 16 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 17 | #include <linux/of.h> | 18 | #include <linux/of.h> |
| 18 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| @@ -120,6 +121,13 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) | |||
| 120 | if (reg == SDHCI_HOST_CONTROL) { | 121 | if (reg == SDHCI_HOST_CONTROL) { |
| 121 | u32 dma_bits; | 122 | u32 dma_bits; |
| 122 | 123 | ||
| 124 | /* | ||
| 125 | * If host control register is not standard, exit | ||
| 126 | * this function | ||
| 127 | */ | ||
| 128 | if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) | ||
| 129 | return; | ||
| 130 | |||
| 123 | /* DMA select is 22,23 bits in Protocol Control Register */ | 131 | /* DMA select is 22,23 bits in Protocol Control Register */ |
| 124 | dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5; | 132 | dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5; |
| 125 | clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5, | 133 | clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5, |
| @@ -200,7 +208,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 200 | } | 208 | } |
| 201 | 209 | ||
| 202 | /* Set the clock */ | 210 | /* Set the clock */ |
| 203 | esdhc_set_clock(host, clock); | 211 | esdhc_set_clock(host, clock, host->max_clk); |
| 204 | } | 212 | } |
| 205 | 213 | ||
| 206 | #ifdef CONFIG_PM | 214 | #ifdef CONFIG_PM |
| @@ -230,6 +238,30 @@ static void esdhc_of_platform_init(struct sdhci_host *host) | |||
| 230 | host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; | 238 | host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; |
| 231 | } | 239 | } |
| 232 | 240 | ||
| 241 | static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width) | ||
| 242 | { | ||
| 243 | u32 ctrl; | ||
| 244 | |||
| 245 | switch (width) { | ||
| 246 | case MMC_BUS_WIDTH_8: | ||
| 247 | ctrl = ESDHC_CTRL_8BITBUS; | ||
| 248 | break; | ||
| 249 | |||
| 250 | case MMC_BUS_WIDTH_4: | ||
| 251 | ctrl = ESDHC_CTRL_4BITBUS; | ||
| 252 | break; | ||
| 253 | |||
| 254 | default: | ||
| 255 | ctrl = 0; | ||
| 256 | break; | ||
| 257 | } | ||
| 258 | |||
| 259 | clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL, | ||
| 260 | ESDHC_CTRL_BUSWIDTH_MASK, ctrl); | ||
| 261 | |||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 233 | static const struct sdhci_ops sdhci_esdhc_ops = { | 265 | static const struct sdhci_ops sdhci_esdhc_ops = { |
| 234 | .read_l = esdhc_readl, | 266 | .read_l = esdhc_readl, |
| 235 | .read_w = esdhc_readw, | 267 | .read_w = esdhc_readw, |
| @@ -247,6 +279,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = { | |||
| 247 | .platform_resume = esdhc_of_resume, | 279 | .platform_resume = esdhc_of_resume, |
| 248 | #endif | 280 | #endif |
| 249 | .adma_workaround = esdhci_of_adma_workaround, | 281 | .adma_workaround = esdhci_of_adma_workaround, |
| 282 | .platform_bus_width = esdhc_pltfm_bus_width, | ||
| 250 | }; | 283 | }; |
| 251 | 284 | ||
| 252 | static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { | 285 | static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { |
| @@ -262,7 +295,33 @@ static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { | |||
| 262 | 295 | ||
| 263 | static int sdhci_esdhc_probe(struct platform_device *pdev) | 296 | static int sdhci_esdhc_probe(struct platform_device *pdev) |
| 264 | { | 297 | { |
| 265 | return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata); | 298 | struct sdhci_host *host; |
| 299 | struct device_node *np; | ||
| 300 | int ret; | ||
| 301 | |||
| 302 | host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0); | ||
| 303 | if (IS_ERR(host)) | ||
| 304 | return PTR_ERR(host); | ||
| 305 | |||
| 306 | sdhci_get_of_property(pdev); | ||
| 307 | |||
| 308 | np = pdev->dev.of_node; | ||
| 309 | if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { | ||
| 310 | /* | ||
| 311 | * Freescale messed up with P2020 as it has a non-standard | ||
| 312 | * host control register | ||
| 313 | */ | ||
| 314 | host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; | ||
| 315 | } | ||
| 316 | |||
| 317 | /* call to generic mmc_of_parse to support additional capabilities */ | ||
| 318 | mmc_of_parse(host->mmc); | ||
| 319 | |||
| 320 | ret = sdhci_add_host(host); | ||
| 321 | if (ret) | ||
| 322 | sdhci_pltfm_free(pdev); | ||
| 323 | |||
| 324 | return ret; | ||
| 266 | } | 325 | } |
| 267 | 326 | ||
| 268 | static int sdhci_esdhc_remove(struct platform_device *pdev) | 327 | static int sdhci_esdhc_remove(struct platform_device *pdev) |
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c index 200a6a9fa805..57c514a81ca5 100644 --- a/drivers/mmc/host/sdhci-of-hlwd.c +++ b/drivers/mmc/host/sdhci-of-hlwd.c | |||
| @@ -68,7 +68,7 @@ static const struct sdhci_pltfm_data sdhci_hlwd_pdata = { | |||
| 68 | 68 | ||
| 69 | static int sdhci_hlwd_probe(struct platform_device *pdev) | 69 | static int sdhci_hlwd_probe(struct platform_device *pdev) |
| 70 | { | 70 | { |
| 71 | return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata); | 71 | return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata, 0); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static int sdhci_hlwd_remove(struct platform_device *pdev) | 74 | static int sdhci_hlwd_remove(struct platform_device *pdev) |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 701d06d0e1fb..d7d6bc8968d2 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC 0x0f14 | 36 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC 0x0f14 |
| 37 | #define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 | 37 | #define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 |
| 38 | #define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 | 38 | #define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 |
| 39 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC2 0x0f50 | ||
| 39 | 40 | ||
| 40 | /* | 41 | /* |
| 41 | * PCI registers | 42 | * PCI registers |
| @@ -77,6 +78,8 @@ struct sdhci_pci_slot { | |||
| 77 | int rst_n_gpio; | 78 | int rst_n_gpio; |
| 78 | int cd_gpio; | 79 | int cd_gpio; |
| 79 | int cd_irq; | 80 | int cd_irq; |
| 81 | |||
| 82 | void (*hw_reset)(struct sdhci_host *host); | ||
| 80 | }; | 83 | }; |
| 81 | 84 | ||
| 82 | struct sdhci_pci_chip { | 85 | struct sdhci_pci_chip { |
| @@ -307,10 +310,27 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = { | |||
| 307 | .probe_slot = pch_hc_probe_slot, | 310 | .probe_slot = pch_hc_probe_slot, |
| 308 | }; | 311 | }; |
| 309 | 312 | ||
| 313 | static void sdhci_pci_int_hw_reset(struct sdhci_host *host) | ||
| 314 | { | ||
| 315 | u8 reg; | ||
| 316 | |||
| 317 | reg = sdhci_readb(host, SDHCI_POWER_CONTROL); | ||
| 318 | reg |= 0x10; | ||
| 319 | sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); | ||
| 320 | /* For eMMC, minimum is 1us but give it 9us for good measure */ | ||
| 321 | udelay(9); | ||
| 322 | reg &= ~0x10; | ||
| 323 | sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); | ||
| 324 | /* For eMMC, minimum is 200us but give it 300us for good measure */ | ||
| 325 | usleep_range(300, 1000); | ||
| 326 | } | ||
| 327 | |||
| 310 | static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) | 328 | static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) |
| 311 | { | 329 | { |
| 312 | slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE; | 330 | slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | |
| 331 | MMC_CAP_HW_RESET; | ||
| 313 | slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ; | 332 | slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ; |
| 333 | slot->hw_reset = sdhci_pci_int_hw_reset; | ||
| 314 | return 0; | 334 | return 0; |
| 315 | } | 335 | } |
| 316 | 336 | ||
| @@ -332,6 +352,8 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { | |||
| 332 | }; | 352 | }; |
| 333 | 353 | ||
| 334 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { | 354 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { |
| 355 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, | ||
| 356 | .allow_runtime_pm = true, | ||
| 335 | }; | 357 | }; |
| 336 | 358 | ||
| 337 | /* O2Micro extra registers */ | 359 | /* O2Micro extra registers */ |
| @@ -910,6 +932,14 @@ static const struct pci_device_id pci_ids[] = { | |||
| 910 | }, | 932 | }, |
| 911 | 933 | ||
| 912 | { | 934 | { |
| 935 | .vendor = PCI_VENDOR_ID_INTEL, | ||
| 936 | .device = PCI_DEVICE_ID_INTEL_BYT_EMMC2, | ||
| 937 | .subvendor = PCI_ANY_ID, | ||
| 938 | .subdevice = PCI_ANY_ID, | ||
| 939 | .driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc, | ||
| 940 | }, | ||
| 941 | |||
| 942 | { | ||
| 913 | .vendor = PCI_VENDOR_ID_O2, | 943 | .vendor = PCI_VENDOR_ID_O2, |
| 914 | .device = PCI_DEVICE_ID_O2_8120, | 944 | .device = PCI_DEVICE_ID_O2_8120, |
| 915 | .subvendor = PCI_ANY_ID, | 945 | .subvendor = PCI_ANY_ID, |
| @@ -1014,7 +1044,7 @@ static int sdhci_pci_bus_width(struct sdhci_host *host, int width) | |||
| 1014 | return 0; | 1044 | return 0; |
| 1015 | } | 1045 | } |
| 1016 | 1046 | ||
| 1017 | static void sdhci_pci_hw_reset(struct sdhci_host *host) | 1047 | static void sdhci_pci_gpio_hw_reset(struct sdhci_host *host) |
| 1018 | { | 1048 | { |
| 1019 | struct sdhci_pci_slot *slot = sdhci_priv(host); | 1049 | struct sdhci_pci_slot *slot = sdhci_priv(host); |
| 1020 | int rst_n_gpio = slot->rst_n_gpio; | 1050 | int rst_n_gpio = slot->rst_n_gpio; |
| @@ -1029,6 +1059,14 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host) | |||
| 1029 | usleep_range(300, 1000); | 1059 | usleep_range(300, 1000); |
| 1030 | } | 1060 | } |
| 1031 | 1061 | ||
| 1062 | static void sdhci_pci_hw_reset(struct sdhci_host *host) | ||
| 1063 | { | ||
| 1064 | struct sdhci_pci_slot *slot = sdhci_priv(host); | ||
| 1065 | |||
| 1066 | if (slot->hw_reset) | ||
| 1067 | slot->hw_reset(host); | ||
| 1068 | } | ||
| 1069 | |||
| 1032 | static const struct sdhci_ops sdhci_pci_ops = { | 1070 | static const struct sdhci_ops sdhci_pci_ops = { |
| 1033 | .enable_dma = sdhci_pci_enable_dma, | 1071 | .enable_dma = sdhci_pci_enable_dma, |
| 1034 | .platform_bus_width = sdhci_pci_bus_width, | 1072 | .platform_bus_width = sdhci_pci_bus_width, |
| @@ -1326,6 +1364,7 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( | |||
| 1326 | if (!gpio_request(slot->rst_n_gpio, "eMMC_reset")) { | 1364 | if (!gpio_request(slot->rst_n_gpio, "eMMC_reset")) { |
| 1327 | gpio_direction_output(slot->rst_n_gpio, 1); | 1365 | gpio_direction_output(slot->rst_n_gpio, 1); |
| 1328 | slot->host->mmc->caps |= MMC_CAP_HW_RESET; | 1366 | slot->host->mmc->caps |= MMC_CAP_HW_RESET; |
| 1367 | slot->hw_reset = sdhci_pci_gpio_hw_reset; | ||
| 1329 | } else { | 1368 | } else { |
| 1330 | dev_warn(&pdev->dev, "failed to request rst_n_gpio\n"); | 1369 | dev_warn(&pdev->dev, "failed to request rst_n_gpio\n"); |
| 1331 | slot->rst_n_gpio = -EINVAL; | 1370 | slot->rst_n_gpio = -EINVAL; |
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index cd0f1f68e261..e2065a44dffc 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
| @@ -115,10 +115,10 @@ void sdhci_get_of_property(struct platform_device *pdev) {} | |||
| 115 | EXPORT_SYMBOL_GPL(sdhci_get_of_property); | 115 | EXPORT_SYMBOL_GPL(sdhci_get_of_property); |
| 116 | 116 | ||
| 117 | struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, | 117 | struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, |
| 118 | const struct sdhci_pltfm_data *pdata) | 118 | const struct sdhci_pltfm_data *pdata, |
| 119 | size_t priv_size) | ||
| 119 | { | 120 | { |
| 120 | struct sdhci_host *host; | 121 | struct sdhci_host *host; |
| 121 | struct sdhci_pltfm_host *pltfm_host; | ||
| 122 | struct device_node *np = pdev->dev.of_node; | 122 | struct device_node *np = pdev->dev.of_node; |
| 123 | struct resource *iomem; | 123 | struct resource *iomem; |
| 124 | int ret; | 124 | int ret; |
| @@ -134,24 +134,27 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, | |||
| 134 | 134 | ||
| 135 | /* Some PCI-based MFD need the parent here */ | 135 | /* Some PCI-based MFD need the parent here */ |
| 136 | if (pdev->dev.parent != &platform_bus && !np) | 136 | if (pdev->dev.parent != &platform_bus && !np) |
| 137 | host = sdhci_alloc_host(pdev->dev.parent, sizeof(*pltfm_host)); | 137 | host = sdhci_alloc_host(pdev->dev.parent, |
| 138 | sizeof(struct sdhci_pltfm_host) + priv_size); | ||
| 138 | else | 139 | else |
| 139 | host = sdhci_alloc_host(&pdev->dev, sizeof(*pltfm_host)); | 140 | host = sdhci_alloc_host(&pdev->dev, |
| 141 | sizeof(struct sdhci_pltfm_host) + priv_size); | ||
| 140 | 142 | ||
| 141 | if (IS_ERR(host)) { | 143 | if (IS_ERR(host)) { |
| 142 | ret = PTR_ERR(host); | 144 | ret = PTR_ERR(host); |
| 143 | goto err; | 145 | goto err; |
| 144 | } | 146 | } |
| 145 | 147 | ||
| 146 | pltfm_host = sdhci_priv(host); | ||
| 147 | |||
| 148 | host->hw_name = dev_name(&pdev->dev); | 148 | host->hw_name = dev_name(&pdev->dev); |
| 149 | if (pdata && pdata->ops) | 149 | if (pdata && pdata->ops) |
| 150 | host->ops = pdata->ops; | 150 | host->ops = pdata->ops; |
| 151 | else | 151 | else |
| 152 | host->ops = &sdhci_pltfm_ops; | 152 | host->ops = &sdhci_pltfm_ops; |
| 153 | if (pdata) | 153 | if (pdata) { |
| 154 | host->quirks = pdata->quirks; | 154 | host->quirks = pdata->quirks; |
| 155 | host->quirks2 = pdata->quirks2; | ||
| 156 | } | ||
| 157 | |||
| 155 | host->irq = platform_get_irq(pdev, 0); | 158 | host->irq = platform_get_irq(pdev, 0); |
| 156 | 159 | ||
| 157 | if (!request_mem_region(iomem->start, resource_size(iomem), | 160 | if (!request_mem_region(iomem->start, resource_size(iomem), |
| @@ -197,17 +200,17 @@ void sdhci_pltfm_free(struct platform_device *pdev) | |||
| 197 | iounmap(host->ioaddr); | 200 | iounmap(host->ioaddr); |
| 198 | release_mem_region(iomem->start, resource_size(iomem)); | 201 | release_mem_region(iomem->start, resource_size(iomem)); |
| 199 | sdhci_free_host(host); | 202 | sdhci_free_host(host); |
| 200 | platform_set_drvdata(pdev, NULL); | ||
| 201 | } | 203 | } |
| 202 | EXPORT_SYMBOL_GPL(sdhci_pltfm_free); | 204 | EXPORT_SYMBOL_GPL(sdhci_pltfm_free); |
| 203 | 205 | ||
| 204 | int sdhci_pltfm_register(struct platform_device *pdev, | 206 | int sdhci_pltfm_register(struct platform_device *pdev, |
| 205 | const struct sdhci_pltfm_data *pdata) | 207 | const struct sdhci_pltfm_data *pdata, |
| 208 | size_t priv_size) | ||
| 206 | { | 209 | { |
| 207 | struct sdhci_host *host; | 210 | struct sdhci_host *host; |
| 208 | int ret = 0; | 211 | int ret = 0; |
| 209 | 212 | ||
| 210 | host = sdhci_pltfm_init(pdev, pdata); | 213 | host = sdhci_pltfm_init(pdev, pdata, priv_size); |
| 211 | if (IS_ERR(host)) | 214 | if (IS_ERR(host)) |
| 212 | return PTR_ERR(host); | 215 | return PTR_ERR(host); |
| 213 | 216 | ||
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index 1210ed1b0c60..e15ced79f7ed 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | struct sdhci_pltfm_data { | 18 | struct sdhci_pltfm_data { |
| 19 | const struct sdhci_ops *ops; | 19 | const struct sdhci_ops *ops; |
| 20 | unsigned int quirks; | 20 | unsigned int quirks; |
| 21 | unsigned int quirks2; | ||
| 21 | }; | 22 | }; |
| 22 | 23 | ||
| 23 | struct sdhci_pltfm_host { | 24 | struct sdhci_pltfm_host { |
| @@ -27,6 +28,8 @@ struct sdhci_pltfm_host { | |||
| 27 | /* migrate from sdhci_of_host */ | 28 | /* migrate from sdhci_of_host */ |
| 28 | unsigned int clock; | 29 | unsigned int clock; |
| 29 | u16 xfer_mode_shadow; | 30 | u16 xfer_mode_shadow; |
| 31 | |||
| 32 | unsigned long private[0] ____cacheline_aligned; | ||
| 30 | }; | 33 | }; |
| 31 | 34 | ||
| 32 | #ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER | 35 | #ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER |
| @@ -91,15 +94,22 @@ static inline void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg) | |||
| 91 | extern void sdhci_get_of_property(struct platform_device *pdev); | 94 | extern void sdhci_get_of_property(struct platform_device *pdev); |
| 92 | 95 | ||
| 93 | extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, | 96 | extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, |
| 94 | const struct sdhci_pltfm_data *pdata); | 97 | const struct sdhci_pltfm_data *pdata, |
| 98 | size_t priv_size); | ||
| 95 | extern void sdhci_pltfm_free(struct platform_device *pdev); | 99 | extern void sdhci_pltfm_free(struct platform_device *pdev); |
| 96 | 100 | ||
| 97 | extern int sdhci_pltfm_register(struct platform_device *pdev, | 101 | extern int sdhci_pltfm_register(struct platform_device *pdev, |
| 98 | const struct sdhci_pltfm_data *pdata); | 102 | const struct sdhci_pltfm_data *pdata, |
| 103 | size_t priv_size); | ||
| 99 | extern int sdhci_pltfm_unregister(struct platform_device *pdev); | 104 | extern int sdhci_pltfm_unregister(struct platform_device *pdev); |
| 100 | 105 | ||
| 101 | extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host); | 106 | extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host); |
| 102 | 107 | ||
| 108 | static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host) | ||
| 109 | { | ||
| 110 | return (void *)host->private; | ||
| 111 | } | ||
| 112 | |||
| 103 | #ifdef CONFIG_PM | 113 | #ifdef CONFIG_PM |
| 104 | extern const struct dev_pm_ops sdhci_pltfm_pmops; | 114 | extern const struct dev_pm_ops sdhci_pltfm_pmops; |
| 105 | #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) | 115 | #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) |
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index 6a3f702a38a6..d51e061ec576 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c | |||
| @@ -175,7 +175,7 @@ static int sdhci_pxav2_probe(struct platform_device *pdev) | |||
| 175 | if (!pxa) | 175 | if (!pxa) |
| 176 | return -ENOMEM; | 176 | return -ENOMEM; |
| 177 | 177 | ||
| 178 | host = sdhci_pltfm_init(pdev, NULL); | 178 | host = sdhci_pltfm_init(pdev, NULL, 0); |
| 179 | if (IS_ERR(host)) { | 179 | if (IS_ERR(host)) { |
| 180 | kfree(pxa); | 180 | kfree(pxa); |
| 181 | return PTR_ERR(host); | 181 | return PTR_ERR(host); |
| @@ -253,8 +253,6 @@ static int sdhci_pxav2_remove(struct platform_device *pdev) | |||
| 253 | sdhci_pltfm_free(pdev); | 253 | sdhci_pltfm_free(pdev); |
| 254 | kfree(pxa); | 254 | kfree(pxa); |
| 255 | 255 | ||
| 256 | platform_set_drvdata(pdev, NULL); | ||
| 257 | |||
| 258 | return 0; | 256 | return 0; |
| 259 | } | 257 | } |
| 260 | 258 | ||
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 1ae358e0662d..bf99359a3a90 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c | |||
| @@ -230,7 +230,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 230 | if (!pxa) | 230 | if (!pxa) |
| 231 | return -ENOMEM; | 231 | return -ENOMEM; |
| 232 | 232 | ||
| 233 | host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata); | 233 | host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata, 0); |
| 234 | if (IS_ERR(host)) { | 234 | if (IS_ERR(host)) { |
| 235 | kfree(pxa); | 235 | kfree(pxa); |
| 236 | return PTR_ERR(host); | 236 | return PTR_ERR(host); |
| @@ -252,7 +252,9 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 252 | 252 | ||
| 253 | match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev); | 253 | match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev); |
| 254 | if (match) { | 254 | if (match) { |
| 255 | mmc_of_parse(host->mmc); | 255 | ret = mmc_of_parse(host->mmc); |
| 256 | if (ret) | ||
| 257 | goto err_of_parse; | ||
| 256 | sdhci_get_of_property(pdev); | 258 | sdhci_get_of_property(pdev); |
| 257 | pdata = pxav3_get_mmc_pdata(dev); | 259 | pdata = pxav3_get_mmc_pdata(dev); |
| 258 | } else if (pdata) { | 260 | } else if (pdata) { |
| @@ -285,18 +287,15 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 285 | } | 287 | } |
| 286 | } | 288 | } |
| 287 | 289 | ||
| 288 | pm_runtime_set_active(&pdev->dev); | ||
| 289 | pm_runtime_enable(&pdev->dev); | 290 | pm_runtime_enable(&pdev->dev); |
| 291 | pm_runtime_get_sync(&pdev->dev); | ||
| 290 | pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS); | 292 | pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS); |
| 291 | pm_runtime_use_autosuspend(&pdev->dev); | 293 | pm_runtime_use_autosuspend(&pdev->dev); |
| 292 | pm_suspend_ignore_children(&pdev->dev, 1); | 294 | pm_suspend_ignore_children(&pdev->dev, 1); |
| 293 | pm_runtime_get_noresume(&pdev->dev); | ||
| 294 | 295 | ||
| 295 | ret = sdhci_add_host(host); | 296 | ret = sdhci_add_host(host); |
| 296 | if (ret) { | 297 | if (ret) { |
| 297 | dev_err(&pdev->dev, "failed to add host\n"); | 298 | dev_err(&pdev->dev, "failed to add host\n"); |
| 298 | pm_runtime_forbid(&pdev->dev); | ||
| 299 | pm_runtime_disable(&pdev->dev); | ||
| 300 | goto err_add_host; | 299 | goto err_add_host; |
| 301 | } | 300 | } |
| 302 | 301 | ||
| @@ -313,10 +312,13 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
| 313 | 312 | ||
| 314 | return 0; | 313 | return 0; |
| 315 | 314 | ||
| 315 | err_of_parse: | ||
| 316 | err_cd_req: | ||
| 316 | err_add_host: | 317 | err_add_host: |
| 318 | pm_runtime_put_sync(&pdev->dev); | ||
| 319 | pm_runtime_disable(&pdev->dev); | ||
| 317 | clk_disable_unprepare(clk); | 320 | clk_disable_unprepare(clk); |
| 318 | clk_put(clk); | 321 | clk_put(clk); |
| 319 | err_cd_req: | ||
| 320 | err_clk_get: | 322 | err_clk_get: |
| 321 | sdhci_pltfm_free(pdev); | 323 | sdhci_pltfm_free(pdev); |
| 322 | kfree(pxa); | 324 | kfree(pxa); |
| @@ -339,8 +341,6 @@ static int sdhci_pxav3_remove(struct platform_device *pdev) | |||
| 339 | sdhci_pltfm_free(pdev); | 341 | sdhci_pltfm_free(pdev); |
| 340 | kfree(pxa); | 342 | kfree(pxa); |
| 341 | 343 | ||
| 342 | platform_set_drvdata(pdev, NULL); | ||
| 343 | |||
| 344 | return 0; | 344 | return 0; |
| 345 | } | 345 | } |
| 346 | 346 | ||
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index c6f6246a4933..926aaf6acc67 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
| @@ -745,7 +745,6 @@ static int sdhci_s3c_remove(struct platform_device *pdev) | |||
| 745 | clk_disable_unprepare(sc->clk_io); | 745 | clk_disable_unprepare(sc->clk_io); |
| 746 | 746 | ||
| 747 | sdhci_free_host(host); | 747 | sdhci_free_host(host); |
| 748 | platform_set_drvdata(pdev, NULL); | ||
| 749 | 748 | ||
| 750 | return 0; | 749 | return 0; |
| 751 | } | 750 | } |
diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c index 09805af0526d..62a4a835acc6 100644 --- a/drivers/mmc/host/sdhci-sirf.c +++ b/drivers/mmc/host/sdhci-sirf.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include <linux/of.h> | 13 | #include <linux/of.h> |
| 14 | #include <linux/of_gpio.h> | 14 | #include <linux/of_gpio.h> |
| 15 | #include <linux/mmc/slot-gpio.h> | 15 | #include <linux/mmc/slot-gpio.h> |
| 16 | #include <linux/pinctrl/consumer.h> | ||
| 17 | #include "sdhci-pltfm.h" | 16 | #include "sdhci-pltfm.h" |
| 18 | 17 | ||
| 19 | struct sdhci_sirf_priv { | 18 | struct sdhci_sirf_priv { |
| @@ -24,7 +23,7 @@ struct sdhci_sirf_priv { | |||
| 24 | static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host) | 23 | static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host) |
| 25 | { | 24 | { |
| 26 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 25 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 27 | struct sdhci_sirf_priv *priv = pltfm_host->priv; | 26 | struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); |
| 28 | return clk_get_rate(priv->clk); | 27 | return clk_get_rate(priv->clk); |
| 29 | } | 28 | } |
| 30 | 29 | ||
| @@ -46,47 +45,35 @@ static int sdhci_sirf_probe(struct platform_device *pdev) | |||
| 46 | struct sdhci_host *host; | 45 | struct sdhci_host *host; |
| 47 | struct sdhci_pltfm_host *pltfm_host; | 46 | struct sdhci_pltfm_host *pltfm_host; |
| 48 | struct sdhci_sirf_priv *priv; | 47 | struct sdhci_sirf_priv *priv; |
| 49 | struct pinctrl *pinctrl; | 48 | struct clk *clk; |
| 49 | int gpio_cd; | ||
| 50 | int ret; | 50 | int ret; |
| 51 | 51 | ||
| 52 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | 52 | clk = devm_clk_get(&pdev->dev, NULL); |
| 53 | if (IS_ERR(pinctrl)) { | 53 | if (IS_ERR(clk)) { |
| 54 | dev_err(&pdev->dev, "unable to get pinmux"); | ||
| 55 | return PTR_ERR(pinctrl); | ||
| 56 | } | ||
| 57 | |||
| 58 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_sirf_priv), | ||
| 59 | GFP_KERNEL); | ||
| 60 | if (!priv) { | ||
| 61 | dev_err(&pdev->dev, "unable to allocate private data"); | ||
| 62 | return -ENOMEM; | ||
| 63 | } | ||
| 64 | |||
| 65 | priv->clk = devm_clk_get(&pdev->dev, NULL); | ||
| 66 | if (IS_ERR(priv->clk)) { | ||
| 67 | dev_err(&pdev->dev, "unable to get clock"); | 54 | dev_err(&pdev->dev, "unable to get clock"); |
| 68 | return PTR_ERR(priv->clk); | 55 | return PTR_ERR(clk); |
| 69 | } | 56 | } |
| 70 | 57 | ||
| 71 | if (pdev->dev.of_node) { | 58 | if (pdev->dev.of_node) |
| 72 | priv->gpio_cd = of_get_named_gpio(pdev->dev.of_node, | 59 | gpio_cd = of_get_named_gpio(pdev->dev.of_node, "cd-gpios", 0); |
| 73 | "cd-gpios", 0); | 60 | else |
| 74 | } else { | 61 | gpio_cd = -EINVAL; |
| 75 | priv->gpio_cd = -EINVAL; | ||
| 76 | } | ||
| 77 | 62 | ||
| 78 | host = sdhci_pltfm_init(pdev, &sdhci_sirf_pdata); | 63 | host = sdhci_pltfm_init(pdev, &sdhci_sirf_pdata, sizeof(struct sdhci_sirf_priv)); |
| 79 | if (IS_ERR(host)) { | 64 | if (IS_ERR(host)) |
| 80 | ret = PTR_ERR(host); | 65 | return PTR_ERR(host); |
| 81 | goto err_sdhci_pltfm_init; | ||
| 82 | } | ||
| 83 | 66 | ||
| 84 | pltfm_host = sdhci_priv(host); | 67 | pltfm_host = sdhci_priv(host); |
| 85 | pltfm_host->priv = priv; | 68 | priv = sdhci_pltfm_priv(pltfm_host); |
| 69 | priv->clk = clk; | ||
| 70 | priv->gpio_cd = gpio_cd; | ||
| 86 | 71 | ||
| 87 | sdhci_get_of_property(pdev); | 72 | sdhci_get_of_property(pdev); |
| 88 | 73 | ||
| 89 | clk_prepare_enable(priv->clk); | 74 | ret = clk_prepare_enable(priv->clk); |
| 75 | if (ret) | ||
| 76 | goto err_clk_prepare; | ||
| 90 | 77 | ||
| 91 | ret = sdhci_add_host(host); | 78 | ret = sdhci_add_host(host); |
| 92 | if (ret) | 79 | if (ret) |
| @@ -111,8 +98,8 @@ err_request_cd: | |||
| 111 | sdhci_remove_host(host, 0); | 98 | sdhci_remove_host(host, 0); |
| 112 | err_sdhci_add: | 99 | err_sdhci_add: |
| 113 | clk_disable_unprepare(priv->clk); | 100 | clk_disable_unprepare(priv->clk); |
| 101 | err_clk_prepare: | ||
| 114 | sdhci_pltfm_free(pdev); | 102 | sdhci_pltfm_free(pdev); |
| 115 | err_sdhci_pltfm_init: | ||
| 116 | return ret; | 103 | return ret; |
| 117 | } | 104 | } |
| 118 | 105 | ||
| @@ -120,7 +107,7 @@ static int sdhci_sirf_remove(struct platform_device *pdev) | |||
| 120 | { | 107 | { |
| 121 | struct sdhci_host *host = platform_get_drvdata(pdev); | 108 | struct sdhci_host *host = platform_get_drvdata(pdev); |
| 122 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 109 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 123 | struct sdhci_sirf_priv *priv = pltfm_host->priv; | 110 | struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); |
| 124 | 111 | ||
| 125 | sdhci_pltfm_unregister(pdev); | 112 | sdhci_pltfm_unregister(pdev); |
| 126 | 113 | ||
| @@ -136,7 +123,7 @@ static int sdhci_sirf_suspend(struct device *dev) | |||
| 136 | { | 123 | { |
| 137 | struct sdhci_host *host = dev_get_drvdata(dev); | 124 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 138 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 125 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 139 | struct sdhci_sirf_priv *priv = pltfm_host->priv; | 126 | struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); |
| 140 | int ret; | 127 | int ret; |
| 141 | 128 | ||
| 142 | ret = sdhci_suspend_host(host); | 129 | ret = sdhci_suspend_host(host); |
| @@ -152,7 +139,7 @@ static int sdhci_sirf_resume(struct device *dev) | |||
| 152 | { | 139 | { |
| 153 | struct sdhci_host *host = dev_get_drvdata(dev); | 140 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 154 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 141 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 155 | struct sdhci_sirf_priv *priv = pltfm_host->priv; | 142 | struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); |
| 156 | int ret; | 143 | int ret; |
| 157 | 144 | ||
| 158 | ret = clk_enable(priv->clk); | 145 | ret = clk_enable(priv->clk); |
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index 7ae5b3ae7bad..2dba9f8d1760 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c | |||
| @@ -258,7 +258,6 @@ static int sdhci_probe(struct platform_device *pdev) | |||
| 258 | return 0; | 258 | return 0; |
| 259 | 259 | ||
| 260 | set_drvdata: | 260 | set_drvdata: |
| 261 | platform_set_drvdata(pdev, NULL); | ||
| 262 | sdhci_remove_host(host, 1); | 261 | sdhci_remove_host(host, 1); |
| 263 | free_host: | 262 | free_host: |
| 264 | sdhci_free_host(host); | 263 | sdhci_free_host(host); |
| @@ -278,7 +277,6 @@ static int sdhci_remove(struct platform_device *pdev) | |||
| 278 | int dead = 0; | 277 | int dead = 0; |
| 279 | u32 scratch; | 278 | u32 scratch; |
| 280 | 279 | ||
| 281 | platform_set_drvdata(pdev, NULL); | ||
| 282 | scratch = readl(host->ioaddr + SDHCI_INT_STATUS); | 280 | scratch = readl(host->ioaddr + SDHCI_INT_STATUS); |
| 283 | if (scratch == (u32)-1) | 281 | if (scratch == (u32)-1) |
| 284 | dead = 1; | 282 | dead = 1; |
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index e0dba74cff98..5b7b2eba8a54 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
| @@ -205,7 +205,7 @@ static const struct of_device_id sdhci_tegra_dt_match[] = { | |||
| 205 | }; | 205 | }; |
| 206 | MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); | 206 | MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); |
| 207 | 207 | ||
| 208 | static void sdhci_tegra_parse_dt(struct device *dev) | 208 | static int sdhci_tegra_parse_dt(struct device *dev) |
| 209 | { | 209 | { |
| 210 | struct device_node *np = dev->of_node; | 210 | struct device_node *np = dev->of_node; |
| 211 | struct sdhci_host *host = dev_get_drvdata(dev); | 211 | struct sdhci_host *host = dev_get_drvdata(dev); |
| @@ -213,7 +213,7 @@ static void sdhci_tegra_parse_dt(struct device *dev) | |||
| 213 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | 213 | struct sdhci_tegra *tegra_host = pltfm_host->priv; |
| 214 | 214 | ||
| 215 | tegra_host->power_gpio = of_get_named_gpio(np, "power-gpios", 0); | 215 | tegra_host->power_gpio = of_get_named_gpio(np, "power-gpios", 0); |
| 216 | mmc_of_parse(host->mmc); | 216 | return mmc_of_parse(host->mmc); |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | static int sdhci_tegra_probe(struct platform_device *pdev) | 219 | static int sdhci_tegra_probe(struct platform_device *pdev) |
| @@ -231,7 +231,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) | |||
| 231 | return -EINVAL; | 231 | return -EINVAL; |
| 232 | soc_data = match->data; | 232 | soc_data = match->data; |
| 233 | 233 | ||
| 234 | host = sdhci_pltfm_init(pdev, soc_data->pdata); | 234 | host = sdhci_pltfm_init(pdev, soc_data->pdata, 0); |
| 235 | if (IS_ERR(host)) | 235 | if (IS_ERR(host)) |
| 236 | return PTR_ERR(host); | 236 | return PTR_ERR(host); |
| 237 | pltfm_host = sdhci_priv(host); | 237 | pltfm_host = sdhci_priv(host); |
| @@ -245,7 +245,9 @@ static int sdhci_tegra_probe(struct platform_device *pdev) | |||
| 245 | tegra_host->soc_data = soc_data; | 245 | tegra_host->soc_data = soc_data; |
| 246 | pltfm_host->priv = tegra_host; | 246 | pltfm_host->priv = tegra_host; |
| 247 | 247 | ||
| 248 | sdhci_tegra_parse_dt(&pdev->dev); | 248 | rc = sdhci_tegra_parse_dt(&pdev->dev); |
| 249 | if (rc) | ||
| 250 | goto err_parse_dt; | ||
| 249 | 251 | ||
| 250 | if (gpio_is_valid(tegra_host->power_gpio)) { | 252 | if (gpio_is_valid(tegra_host->power_gpio)) { |
| 251 | rc = gpio_request(tegra_host->power_gpio, "sdhci_power"); | 253 | rc = gpio_request(tegra_host->power_gpio, "sdhci_power"); |
| @@ -279,6 +281,7 @@ err_clk_get: | |||
| 279 | if (gpio_is_valid(tegra_host->power_gpio)) | 281 | if (gpio_is_valid(tegra_host->power_gpio)) |
| 280 | gpio_free(tegra_host->power_gpio); | 282 | gpio_free(tegra_host->power_gpio); |
| 281 | err_power_req: | 283 | err_power_req: |
| 284 | err_parse_dt: | ||
| 282 | err_alloc_tegra_host: | 285 | err_alloc_tegra_host: |
| 283 | sdhci_pltfm_free(pdev); | 286 | sdhci_pltfm_free(pdev); |
| 284 | return rc; | 287 | return rc; |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2ea429c27714..a78bd4f3aecc 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -58,6 +58,8 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); | |||
| 58 | #ifdef CONFIG_PM_RUNTIME | 58 | #ifdef CONFIG_PM_RUNTIME |
| 59 | static int sdhci_runtime_pm_get(struct sdhci_host *host); | 59 | static int sdhci_runtime_pm_get(struct sdhci_host *host); |
| 60 | static int sdhci_runtime_pm_put(struct sdhci_host *host); | 60 | static int sdhci_runtime_pm_put(struct sdhci_host *host); |
| 61 | static void sdhci_runtime_pm_bus_on(struct sdhci_host *host); | ||
| 62 | static void sdhci_runtime_pm_bus_off(struct sdhci_host *host); | ||
| 61 | #else | 63 | #else |
| 62 | static inline int sdhci_runtime_pm_get(struct sdhci_host *host) | 64 | static inline int sdhci_runtime_pm_get(struct sdhci_host *host) |
| 63 | { | 65 | { |
| @@ -67,6 +69,12 @@ static inline int sdhci_runtime_pm_put(struct sdhci_host *host) | |||
| 67 | { | 69 | { |
| 68 | return 0; | 70 | return 0; |
| 69 | } | 71 | } |
| 72 | static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) | ||
| 73 | { | ||
| 74 | } | ||
| 75 | static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) | ||
| 76 | { | ||
| 77 | } | ||
| 70 | #endif | 78 | #endif |
| 71 | 79 | ||
| 72 | static void sdhci_dumpregs(struct sdhci_host *host) | 80 | static void sdhci_dumpregs(struct sdhci_host *host) |
| @@ -192,8 +200,12 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) | |||
| 192 | 200 | ||
| 193 | sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); | 201 | sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); |
| 194 | 202 | ||
| 195 | if (mask & SDHCI_RESET_ALL) | 203 | if (mask & SDHCI_RESET_ALL) { |
| 196 | host->clock = 0; | 204 | host->clock = 0; |
| 205 | /* Reset-all turns off SD Bus Power */ | ||
| 206 | if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) | ||
| 207 | sdhci_runtime_pm_bus_off(host); | ||
| 208 | } | ||
| 197 | 209 | ||
| 198 | /* Wait max 100 ms */ | 210 | /* Wait max 100 ms */ |
| 199 | timeout = 100; | 211 | timeout = 100; |
| @@ -1268,6 +1280,8 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
| 1268 | 1280 | ||
| 1269 | if (pwr == 0) { | 1281 | if (pwr == 0) { |
| 1270 | sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); | 1282 | sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); |
| 1283 | if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) | ||
| 1284 | sdhci_runtime_pm_bus_off(host); | ||
| 1271 | return 0; | 1285 | return 0; |
| 1272 | } | 1286 | } |
| 1273 | 1287 | ||
| @@ -1289,6 +1303,9 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
| 1289 | 1303 | ||
| 1290 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | 1304 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); |
| 1291 | 1305 | ||
| 1306 | if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) | ||
| 1307 | sdhci_runtime_pm_bus_on(host); | ||
| 1308 | |||
| 1292 | /* | 1309 | /* |
| 1293 | * Some controllers need an extra 10ms delay of 10ms before they | 1310 | * Some controllers need an extra 10ms delay of 10ms before they |
| 1294 | * can apply clock after applying power | 1311 | * can apply clock after applying power |
| @@ -1526,16 +1543,15 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) | |||
| 1526 | ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1543 | ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
| 1527 | /* Select Bus Speed Mode for host */ | 1544 | /* Select Bus Speed Mode for host */ |
| 1528 | ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; | 1545 | ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; |
| 1529 | if (ios->timing == MMC_TIMING_MMC_HS200) | 1546 | if ((ios->timing == MMC_TIMING_MMC_HS200) || |
| 1530 | ctrl_2 |= SDHCI_CTRL_HS_SDR200; | 1547 | (ios->timing == MMC_TIMING_UHS_SDR104)) |
| 1548 | ctrl_2 |= SDHCI_CTRL_UHS_SDR104; | ||
| 1531 | else if (ios->timing == MMC_TIMING_UHS_SDR12) | 1549 | else if (ios->timing == MMC_TIMING_UHS_SDR12) |
| 1532 | ctrl_2 |= SDHCI_CTRL_UHS_SDR12; | 1550 | ctrl_2 |= SDHCI_CTRL_UHS_SDR12; |
| 1533 | else if (ios->timing == MMC_TIMING_UHS_SDR25) | 1551 | else if (ios->timing == MMC_TIMING_UHS_SDR25) |
| 1534 | ctrl_2 |= SDHCI_CTRL_UHS_SDR25; | 1552 | ctrl_2 |= SDHCI_CTRL_UHS_SDR25; |
| 1535 | else if (ios->timing == MMC_TIMING_UHS_SDR50) | 1553 | else if (ios->timing == MMC_TIMING_UHS_SDR50) |
| 1536 | ctrl_2 |= SDHCI_CTRL_UHS_SDR50; | 1554 | ctrl_2 |= SDHCI_CTRL_UHS_SDR50; |
| 1537 | else if (ios->timing == MMC_TIMING_UHS_SDR104) | ||
| 1538 | ctrl_2 |= SDHCI_CTRL_UHS_SDR104; | ||
| 1539 | else if (ios->timing == MMC_TIMING_UHS_DDR50) | 1555 | else if (ios->timing == MMC_TIMING_UHS_DDR50) |
| 1540 | ctrl_2 |= SDHCI_CTRL_UHS_DDR50; | 1556 | ctrl_2 |= SDHCI_CTRL_UHS_DDR50; |
| 1541 | sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); | 1557 | sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); |
| @@ -1846,7 +1862,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 1846 | */ | 1862 | */ |
| 1847 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && | 1863 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && |
| 1848 | (host->flags & SDHCI_SDR50_NEEDS_TUNING || | 1864 | (host->flags & SDHCI_SDR50_NEEDS_TUNING || |
| 1849 | host->flags & SDHCI_HS200_NEEDS_TUNING)) | 1865 | host->flags & SDHCI_SDR104_NEEDS_TUNING)) |
| 1850 | requires_tuning_nonuhs = true; | 1866 | requires_tuning_nonuhs = true; |
| 1851 | 1867 | ||
| 1852 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || | 1868 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || |
| @@ -2046,11 +2062,14 @@ static void sdhci_card_event(struct mmc_host *mmc) | |||
| 2046 | struct sdhci_host *host = mmc_priv(mmc); | 2062 | struct sdhci_host *host = mmc_priv(mmc); |
| 2047 | unsigned long flags; | 2063 | unsigned long flags; |
| 2048 | 2064 | ||
| 2065 | /* First check if client has provided their own card event */ | ||
| 2066 | if (host->ops->card_event) | ||
| 2067 | host->ops->card_event(host); | ||
| 2068 | |||
| 2049 | spin_lock_irqsave(&host->lock, flags); | 2069 | spin_lock_irqsave(&host->lock, flags); |
| 2050 | 2070 | ||
| 2051 | /* Check host->mrq first in case we are runtime suspended */ | 2071 | /* Check host->mrq first in case we are runtime suspended */ |
| 2052 | if (host->mrq && | 2072 | if (host->mrq && !sdhci_do_get_cd(host)) { |
| 2053 | !(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { | ||
| 2054 | pr_err("%s: Card removed during transfer!\n", | 2073 | pr_err("%s: Card removed during transfer!\n", |
| 2055 | mmc_hostname(host->mmc)); | 2074 | mmc_hostname(host->mmc)); |
| 2056 | pr_err("%s: Resetting controller.\n", | 2075 | pr_err("%s: Resetting controller.\n", |
| @@ -2625,6 +2644,22 @@ static int sdhci_runtime_pm_put(struct sdhci_host *host) | |||
| 2625 | return pm_runtime_put_autosuspend(host->mmc->parent); | 2644 | return pm_runtime_put_autosuspend(host->mmc->parent); |
| 2626 | } | 2645 | } |
| 2627 | 2646 | ||
| 2647 | static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) | ||
| 2648 | { | ||
| 2649 | if (host->runtime_suspended || host->bus_on) | ||
| 2650 | return; | ||
| 2651 | host->bus_on = true; | ||
| 2652 | pm_runtime_get_noresume(host->mmc->parent); | ||
| 2653 | } | ||
| 2654 | |||
| 2655 | static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) | ||
| 2656 | { | ||
| 2657 | if (host->runtime_suspended || !host->bus_on) | ||
| 2658 | return; | ||
| 2659 | host->bus_on = false; | ||
| 2660 | pm_runtime_put_noidle(host->mmc->parent); | ||
| 2661 | } | ||
| 2662 | |||
| 2628 | int sdhci_runtime_suspend_host(struct sdhci_host *host) | 2663 | int sdhci_runtime_suspend_host(struct sdhci_host *host) |
| 2629 | { | 2664 | { |
| 2630 | unsigned long flags; | 2665 | unsigned long flags; |
| @@ -2962,9 +2997,13 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 2962 | mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; | 2997 | mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; |
| 2963 | 2998 | ||
| 2964 | /* SDR104 supports also implies SDR50 support */ | 2999 | /* SDR104 supports also implies SDR50 support */ |
| 2965 | if (caps[1] & SDHCI_SUPPORT_SDR104) | 3000 | if (caps[1] & SDHCI_SUPPORT_SDR104) { |
| 2966 | mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; | 3001 | mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; |
| 2967 | else if (caps[1] & SDHCI_SUPPORT_SDR50) | 3002 | /* SD3.0: SDR104 is supported so (for eMMC) the caps2 |
| 3003 | * field can be promoted to support HS200. | ||
| 3004 | */ | ||
| 3005 | mmc->caps2 |= MMC_CAP2_HS200; | ||
| 3006 | } else if (caps[1] & SDHCI_SUPPORT_SDR50) | ||
| 2968 | mmc->caps |= MMC_CAP_UHS_SDR50; | 3007 | mmc->caps |= MMC_CAP_UHS_SDR50; |
| 2969 | 3008 | ||
| 2970 | if (caps[1] & SDHCI_SUPPORT_DDR50) | 3009 | if (caps[1] & SDHCI_SUPPORT_DDR50) |
| @@ -2974,9 +3013,9 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 2974 | if (caps[1] & SDHCI_USE_SDR50_TUNING) | 3013 | if (caps[1] & SDHCI_USE_SDR50_TUNING) |
| 2975 | host->flags |= SDHCI_SDR50_NEEDS_TUNING; | 3014 | host->flags |= SDHCI_SDR50_NEEDS_TUNING; |
| 2976 | 3015 | ||
| 2977 | /* Does the host need tuning for HS200? */ | 3016 | /* Does the host need tuning for SDR104 / HS200? */ |
| 2978 | if (mmc->caps2 & MMC_CAP2_HS200) | 3017 | if (mmc->caps2 & MMC_CAP2_HS200) |
| 2979 | host->flags |= SDHCI_HS200_NEEDS_TUNING; | 3018 | host->flags |= SDHCI_SDR104_NEEDS_TUNING; |
| 2980 | 3019 | ||
| 2981 | /* Driver Type(s) (A, C, D) supported by the host */ | 3020 | /* Driver Type(s) (A, C, D) supported by the host */ |
| 2982 | if (caps[1] & SDHCI_DRIVER_TYPE_A) | 3021 | if (caps[1] & SDHCI_DRIVER_TYPE_A) |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 379e09d9f3c1..b037f188fe44 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
| @@ -294,6 +294,7 @@ struct sdhci_ops { | |||
| 294 | void (*platform_resume)(struct sdhci_host *host); | 294 | void (*platform_resume)(struct sdhci_host *host); |
| 295 | void (*adma_workaround)(struct sdhci_host *host, u32 intmask); | 295 | void (*adma_workaround)(struct sdhci_host *host, u32 intmask); |
| 296 | void (*platform_init)(struct sdhci_host *host); | 296 | void (*platform_init)(struct sdhci_host *host); |
| 297 | void (*card_event)(struct sdhci_host *host); | ||
| 297 | }; | 298 | }; |
| 298 | 299 | ||
| 299 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS | 300 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index ba76a532ae30..6706b5e3b974 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
| @@ -1244,7 +1244,8 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | |||
| 1244 | u32 state; | 1244 | u32 state; |
| 1245 | 1245 | ||
| 1246 | state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); | 1246 | state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); |
| 1247 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); | 1247 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, |
| 1248 | ~(state & sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK))); | ||
| 1248 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN); | 1249 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN); |
| 1249 | 1250 | ||
| 1250 | if (state & ~MASK_CLEAN) | 1251 | if (state & ~MASK_CLEAN) |
| @@ -1369,7 +1370,11 @@ static int sh_mmcif_probe(struct platform_device *pdev) | |||
| 1369 | ret = -ENOMEM; | 1370 | ret = -ENOMEM; |
| 1370 | goto ealloch; | 1371 | goto ealloch; |
| 1371 | } | 1372 | } |
| 1372 | mmc_of_parse(mmc); | 1373 | |
| 1374 | ret = mmc_of_parse(mmc); | ||
| 1375 | if (ret < 0) | ||
| 1376 | goto eofparse; | ||
| 1377 | |||
| 1373 | host = mmc_priv(mmc); | 1378 | host = mmc_priv(mmc); |
| 1374 | host->mmc = mmc; | 1379 | host->mmc = mmc; |
| 1375 | host->addr = reg; | 1380 | host->addr = reg; |
| @@ -1464,6 +1469,7 @@ eclkupdate: | |||
| 1464 | clk_put(host->hclk); | 1469 | clk_put(host->hclk); |
| 1465 | eclkget: | 1470 | eclkget: |
| 1466 | pm_runtime_disable(&pdev->dev); | 1471 | pm_runtime_disable(&pdev->dev); |
| 1472 | eofparse: | ||
| 1467 | mmc_free_host(mmc); | 1473 | mmc_free_host(mmc); |
| 1468 | ealloch: | 1474 | ealloch: |
| 1469 | iounmap(reg); | 1475 | iounmap(reg); |
| @@ -1501,8 +1507,6 @@ static int sh_mmcif_remove(struct platform_device *pdev) | |||
| 1501 | if (irq[1] >= 0) | 1507 | if (irq[1] >= 0) |
| 1502 | free_irq(irq[1], host); | 1508 | free_irq(irq[1], host); |
| 1503 | 1509 | ||
| 1504 | platform_set_drvdata(pdev, NULL); | ||
| 1505 | |||
| 1506 | clk_disable(host->hclk); | 1510 | clk_disable(host->hclk); |
| 1507 | mmc_free_host(host->mmc); | 1511 | mmc_free_host(host->mmc); |
| 1508 | pm_runtime_put_sync(&pdev->dev); | 1512 | pm_runtime_put_sync(&pdev->dev); |
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index fe90853900b4..ebea749297c2 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c | |||
| @@ -46,14 +46,12 @@ static const struct sh_mobile_sdhi_of_data sh_mobile_sdhi_of_cfg[] = { | |||
| 46 | struct sh_mobile_sdhi { | 46 | struct sh_mobile_sdhi { |
| 47 | struct clk *clk; | 47 | struct clk *clk; |
| 48 | struct tmio_mmc_data mmc_data; | 48 | struct tmio_mmc_data mmc_data; |
| 49 | struct sh_dmae_slave param_tx; | ||
| 50 | struct sh_dmae_slave param_rx; | ||
| 51 | struct tmio_mmc_dma dma_priv; | 49 | struct tmio_mmc_dma dma_priv; |
| 52 | }; | 50 | }; |
| 53 | 51 | ||
| 54 | static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f) | 52 | static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f) |
| 55 | { | 53 | { |
| 56 | struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); | 54 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 57 | struct tmio_mmc_host *host = mmc_priv(mmc); | 55 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 58 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); | 56 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); |
| 59 | int ret = clk_enable(priv->clk); | 57 | int ret = clk_enable(priv->clk); |
| @@ -66,7 +64,7 @@ static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int | |||
| 66 | 64 | ||
| 67 | static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev) | 65 | static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev) |
| 68 | { | 66 | { |
| 69 | struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); | 67 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 70 | struct tmio_mmc_host *host = mmc_priv(mmc); | 68 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 71 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); | 69 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); |
| 72 | clk_disable(priv->clk); | 70 | clk_disable(priv->clk); |
| @@ -121,7 +119,7 @@ static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) | |||
| 121 | 119 | ||
| 122 | static void sh_mobile_sdhi_cd_wakeup(const struct platform_device *pdev) | 120 | static void sh_mobile_sdhi_cd_wakeup(const struct platform_device *pdev) |
| 123 | { | 121 | { |
| 124 | mmc_detect_change(dev_get_drvdata(&pdev->dev), msecs_to_jiffies(100)); | 122 | mmc_detect_change(platform_get_drvdata(pdev), msecs_to_jiffies(100)); |
| 125 | } | 123 | } |
| 126 | 124 | ||
| 127 | static const struct sh_mobile_sdhi_ops sdhi_ops = { | 125 | static const struct sh_mobile_sdhi_ops sdhi_ops = { |
| @@ -146,6 +144,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 146 | struct tmio_mmc_host *host; | 144 | struct tmio_mmc_host *host; |
| 147 | int irq, ret, i = 0; | 145 | int irq, ret, i = 0; |
| 148 | bool multiplexed_isr = true; | 146 | bool multiplexed_isr = true; |
| 147 | struct tmio_mmc_dma *dma_priv; | ||
| 149 | 148 | ||
| 150 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_mobile_sdhi), GFP_KERNEL); | 149 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_mobile_sdhi), GFP_KERNEL); |
| 151 | if (priv == NULL) { | 150 | if (priv == NULL) { |
| @@ -154,6 +153,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 154 | } | 153 | } |
| 155 | 154 | ||
| 156 | mmc_data = &priv->mmc_data; | 155 | mmc_data = &priv->mmc_data; |
| 156 | dma_priv = &priv->dma_priv; | ||
| 157 | 157 | ||
| 158 | if (p) { | 158 | if (p) { |
| 159 | if (p->init) { | 159 | if (p->init) { |
| @@ -186,15 +186,23 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 186 | mmc_data->get_cd = sh_mobile_sdhi_get_cd; | 186 | mmc_data->get_cd = sh_mobile_sdhi_get_cd; |
| 187 | 187 | ||
| 188 | if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) { | 188 | if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) { |
| 189 | priv->param_tx.shdma_slave.slave_id = p->dma_slave_tx; | 189 | /* |
| 190 | priv->param_rx.shdma_slave.slave_id = p->dma_slave_rx; | 190 | * Yes, we have to provide slave IDs twice to TMIO: |
| 191 | priv->dma_priv.chan_priv_tx = &priv->param_tx.shdma_slave; | 191 | * once as a filter parameter and once for channel |
| 192 | priv->dma_priv.chan_priv_rx = &priv->param_rx.shdma_slave; | 192 | * configuration as an explicit slave ID |
| 193 | priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */ | 193 | */ |
| 194 | mmc_data->dma = &priv->dma_priv; | 194 | dma_priv->chan_priv_tx = (void *)p->dma_slave_tx; |
| 195 | dma_priv->chan_priv_rx = (void *)p->dma_slave_rx; | ||
| 196 | dma_priv->slave_id_tx = p->dma_slave_tx; | ||
| 197 | dma_priv->slave_id_rx = p->dma_slave_rx; | ||
| 195 | } | 198 | } |
| 196 | } | 199 | } |
| 197 | 200 | ||
| 201 | dma_priv->alignment_shift = 1; /* 2-byte alignment */ | ||
| 202 | dma_priv->filter = shdma_chan_filter; | ||
| 203 | |||
| 204 | mmc_data->dma = dma_priv; | ||
| 205 | |||
| 198 | /* | 206 | /* |
| 199 | * All SDHI blocks support 2-byte and larger block sizes in 4-bit | 207 | * All SDHI blocks support 2-byte and larger block sizes in 4-bit |
| 200 | * bus width mode. | 208 | * bus width mode. |
| @@ -265,8 +273,10 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 265 | } | 273 | } |
| 266 | 274 | ||
| 267 | /* There must be at least one IRQ source */ | 275 | /* There must be at least one IRQ source */ |
| 268 | if (!i) | 276 | if (!i) { |
| 277 | ret = irq; | ||
| 269 | goto eirq; | 278 | goto eirq; |
| 279 | } | ||
| 270 | } | 280 | } |
| 271 | 281 | ||
| 272 | dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n", | 282 | dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n", |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 139212e79cde..8860d4d2bc22 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
| @@ -112,8 +112,6 @@ static int tmio_mmc_remove(struct platform_device *pdev) | |||
| 112 | const struct mfd_cell *cell = mfd_get_cell(pdev); | 112 | const struct mfd_cell *cell = mfd_get_cell(pdev); |
| 113 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 113 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 114 | 114 | ||
| 115 | platform_set_drvdata(pdev, NULL); | ||
| 116 | |||
| 117 | if (mmc) { | 115 | if (mmc) { |
| 118 | struct tmio_mmc_host *host = mmc_priv(mmc); | 116 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 119 | free_irq(platform_get_irq(pdev, 0), host); | 117 | free_irq(platform_get_irq(pdev, 0), host); |
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index d857f5c6e7d9..86fd21e00099 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h | |||
| @@ -40,6 +40,22 @@ | |||
| 40 | 40 | ||
| 41 | struct tmio_mmc_data; | 41 | struct tmio_mmc_data; |
| 42 | 42 | ||
| 43 | /* | ||
| 44 | * We differentiate between the following 3 power states: | ||
| 45 | * 1. card slot powered off, controller stopped. This is used, when either there | ||
| 46 | * is no card in the slot, or the card really has to be powered down. | ||
| 47 | * 2. card slot powered on, controller stopped. This is used, when a card is in | ||
| 48 | * the slot, but no activity is currently taking place. This is a power- | ||
| 49 | * saving mode with card-state preserved. This state can be entered, e.g. | ||
| 50 | * when MMC clock-gating is used. | ||
| 51 | * 3. card slot powered on, controller running. This is the actual active state. | ||
| 52 | */ | ||
| 53 | enum tmio_mmc_power { | ||
| 54 | TMIO_MMC_OFF_STOP, /* card power off, controller stopped */ | ||
| 55 | TMIO_MMC_ON_STOP, /* card power on, controller stopped */ | ||
| 56 | TMIO_MMC_ON_RUN, /* card power on, controller running */ | ||
| 57 | }; | ||
| 58 | |||
| 43 | struct tmio_mmc_host { | 59 | struct tmio_mmc_host { |
| 44 | void __iomem *ctl; | 60 | void __iomem *ctl; |
| 45 | unsigned long bus_shift; | 61 | unsigned long bus_shift; |
| @@ -48,8 +64,8 @@ struct tmio_mmc_host { | |||
| 48 | struct mmc_data *data; | 64 | struct mmc_data *data; |
| 49 | struct mmc_host *mmc; | 65 | struct mmc_host *mmc; |
| 50 | 66 | ||
| 51 | /* Controller power state */ | 67 | /* Controller and card power state */ |
| 52 | bool power; | 68 | enum tmio_mmc_power power; |
| 53 | 69 | ||
| 54 | /* Callbacks for clock / power control */ | 70 | /* Callbacks for clock / power control */ |
| 55 | void (*set_pwr)(struct platform_device *host, int state); | 71 | void (*set_pwr)(struct platform_device *host, int state); |
| @@ -85,6 +101,7 @@ struct tmio_mmc_host { | |||
| 85 | unsigned long last_req_ts; | 101 | unsigned long last_req_ts; |
| 86 | struct mutex ios_lock; /* protect set_ios() context */ | 102 | struct mutex ios_lock; /* protect set_ios() context */ |
| 87 | bool native_hotplug; | 103 | bool native_hotplug; |
| 104 | bool resuming; | ||
| 88 | }; | 105 | }; |
| 89 | 106 | ||
| 90 | int tmio_mmc_host_probe(struct tmio_mmc_host **host, | 107 | int tmio_mmc_host_probe(struct tmio_mmc_host **host, |
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index fff928604859..47bdb8fa341b 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c | |||
| @@ -261,42 +261,62 @@ out: | |||
| 261 | spin_unlock_irq(&host->lock); | 261 | spin_unlock_irq(&host->lock); |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | /* It might be necessary to make filter MFD specific */ | ||
| 265 | static bool tmio_mmc_filter(struct dma_chan *chan, void *arg) | ||
| 266 | { | ||
| 267 | dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg); | ||
| 268 | chan->private = arg; | ||
| 269 | return true; | ||
| 270 | } | ||
| 271 | |||
| 272 | void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata) | 264 | void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata) |
| 273 | { | 265 | { |
| 274 | /* We can only either use DMA for both Tx and Rx or not use it at all */ | 266 | /* We can only either use DMA for both Tx and Rx or not use it at all */ |
| 275 | if (!pdata->dma) | 267 | if (!pdata->dma || (!host->pdev->dev.of_node && |
| 268 | (!pdata->dma->chan_priv_tx || !pdata->dma->chan_priv_rx))) | ||
| 276 | return; | 269 | return; |
| 277 | 270 | ||
| 278 | if (!host->chan_tx && !host->chan_rx) { | 271 | if (!host->chan_tx && !host->chan_rx) { |
| 272 | struct resource *res = platform_get_resource(host->pdev, | ||
| 273 | IORESOURCE_MEM, 0); | ||
| 274 | struct dma_slave_config cfg = {}; | ||
| 279 | dma_cap_mask_t mask; | 275 | dma_cap_mask_t mask; |
| 276 | int ret; | ||
| 277 | |||
| 278 | if (!res) | ||
| 279 | return; | ||
| 280 | 280 | ||
| 281 | dma_cap_zero(mask); | 281 | dma_cap_zero(mask); |
| 282 | dma_cap_set(DMA_SLAVE, mask); | 282 | dma_cap_set(DMA_SLAVE, mask); |
| 283 | 283 | ||
| 284 | host->chan_tx = dma_request_channel(mask, tmio_mmc_filter, | 284 | host->chan_tx = dma_request_slave_channel_compat(mask, |
| 285 | pdata->dma->chan_priv_tx); | 285 | pdata->dma->filter, pdata->dma->chan_priv_tx, |
| 286 | &host->pdev->dev, "tx"); | ||
| 286 | dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__, | 287 | dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__, |
| 287 | host->chan_tx); | 288 | host->chan_tx); |
| 288 | 289 | ||
| 289 | if (!host->chan_tx) | 290 | if (!host->chan_tx) |
| 290 | return; | 291 | return; |
| 291 | 292 | ||
| 292 | host->chan_rx = dma_request_channel(mask, tmio_mmc_filter, | 293 | if (pdata->dma->chan_priv_tx) |
| 293 | pdata->dma->chan_priv_rx); | 294 | cfg.slave_id = pdata->dma->slave_id_tx; |
| 295 | cfg.direction = DMA_MEM_TO_DEV; | ||
| 296 | cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->bus_shift); | ||
| 297 | cfg.src_addr = 0; | ||
| 298 | ret = dmaengine_slave_config(host->chan_tx, &cfg); | ||
| 299 | if (ret < 0) | ||
| 300 | goto ecfgtx; | ||
| 301 | |||
| 302 | host->chan_rx = dma_request_slave_channel_compat(mask, | ||
| 303 | pdata->dma->filter, pdata->dma->chan_priv_rx, | ||
| 304 | &host->pdev->dev, "rx"); | ||
| 294 | dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__, | 305 | dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__, |
| 295 | host->chan_rx); | 306 | host->chan_rx); |
| 296 | 307 | ||
| 297 | if (!host->chan_rx) | 308 | if (!host->chan_rx) |
| 298 | goto ereqrx; | 309 | goto ereqrx; |
| 299 | 310 | ||
| 311 | if (pdata->dma->chan_priv_rx) | ||
| 312 | cfg.slave_id = pdata->dma->slave_id_rx; | ||
| 313 | cfg.direction = DMA_DEV_TO_MEM; | ||
| 314 | cfg.src_addr = cfg.dst_addr; | ||
| 315 | cfg.dst_addr = 0; | ||
| 316 | ret = dmaengine_slave_config(host->chan_rx, &cfg); | ||
| 317 | if (ret < 0) | ||
| 318 | goto ecfgrx; | ||
| 319 | |||
| 300 | host->bounce_buf = (u8 *)__get_free_page(GFP_KERNEL | GFP_DMA); | 320 | host->bounce_buf = (u8 *)__get_free_page(GFP_KERNEL | GFP_DMA); |
| 301 | if (!host->bounce_buf) | 321 | if (!host->bounce_buf) |
| 302 | goto ebouncebuf; | 322 | goto ebouncebuf; |
| @@ -310,9 +330,11 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat | |||
| 310 | return; | 330 | return; |
| 311 | 331 | ||
| 312 | ebouncebuf: | 332 | ebouncebuf: |
| 333 | ecfgrx: | ||
| 313 | dma_release_channel(host->chan_rx); | 334 | dma_release_channel(host->chan_rx); |
| 314 | host->chan_rx = NULL; | 335 | host->chan_rx = NULL; |
| 315 | ereqrx: | 336 | ereqrx: |
| 337 | ecfgtx: | ||
| 316 | dma_release_channel(host->chan_tx); | 338 | dma_release_channel(host->chan_tx); |
| 317 | host->chan_tx = NULL; | 339 | host->chan_tx = NULL; |
| 318 | } | 340 | } |
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index f508ecb5b8a7..b72edb72f7d2 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
| @@ -859,32 +859,45 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 859 | * is kept positive, so no suspending actually takes place. | 859 | * is kept positive, so no suspending actually takes place. |
| 860 | */ | 860 | */ |
| 861 | if (ios->power_mode == MMC_POWER_ON && ios->clock) { | 861 | if (ios->power_mode == MMC_POWER_ON && ios->clock) { |
| 862 | if (!host->power) { | 862 | if (host->power != TMIO_MMC_ON_RUN) { |
| 863 | tmio_mmc_clk_update(mmc); | 863 | tmio_mmc_clk_update(mmc); |
| 864 | pm_runtime_get_sync(dev); | 864 | pm_runtime_get_sync(dev); |
| 865 | if (host->resuming) { | ||
| 866 | tmio_mmc_reset(host); | ||
| 867 | host->resuming = false; | ||
| 868 | } | ||
| 865 | } | 869 | } |
| 870 | if (host->power == TMIO_MMC_OFF_STOP) | ||
| 871 | tmio_mmc_reset(host); | ||
| 866 | tmio_mmc_set_clock(host, ios->clock); | 872 | tmio_mmc_set_clock(host, ios->clock); |
| 867 | if (!host->power) { | 873 | if (host->power == TMIO_MMC_OFF_STOP) |
| 868 | /* power up SD card and the bus */ | 874 | /* power up SD card and the bus */ |
| 869 | tmio_mmc_power_on(host, ios->vdd); | 875 | tmio_mmc_power_on(host, ios->vdd); |
| 870 | host->power = true; | 876 | host->power = TMIO_MMC_ON_RUN; |
| 871 | } | ||
| 872 | /* start bus clock */ | 877 | /* start bus clock */ |
| 873 | tmio_mmc_clk_start(host); | 878 | tmio_mmc_clk_start(host); |
| 874 | } else if (ios->power_mode != MMC_POWER_UP) { | 879 | } else if (ios->power_mode != MMC_POWER_UP) { |
| 875 | if (host->power) { | 880 | struct tmio_mmc_data *pdata = host->pdata; |
| 876 | struct tmio_mmc_data *pdata = host->pdata; | 881 | unsigned int old_power = host->power; |
| 877 | if (ios->power_mode == MMC_POWER_OFF) | 882 | |
| 883 | if (old_power != TMIO_MMC_OFF_STOP) { | ||
| 884 | if (ios->power_mode == MMC_POWER_OFF) { | ||
| 878 | tmio_mmc_power_off(host); | 885 | tmio_mmc_power_off(host); |
| 886 | host->power = TMIO_MMC_OFF_STOP; | ||
| 887 | } else { | ||
| 888 | host->power = TMIO_MMC_ON_STOP; | ||
| 889 | } | ||
| 890 | } | ||
| 891 | |||
| 892 | if (old_power == TMIO_MMC_ON_RUN) { | ||
| 879 | tmio_mmc_clk_stop(host); | 893 | tmio_mmc_clk_stop(host); |
| 880 | host->power = false; | ||
| 881 | pm_runtime_put(dev); | 894 | pm_runtime_put(dev); |
| 882 | if (pdata->clk_disable) | 895 | if (pdata->clk_disable) |
| 883 | pdata->clk_disable(host->pdev); | 896 | pdata->clk_disable(host->pdev); |
| 884 | } | 897 | } |
| 885 | } | 898 | } |
| 886 | 899 | ||
| 887 | if (host->power) { | 900 | if (host->power != TMIO_MMC_OFF_STOP) { |
| 888 | switch (ios->bus_width) { | 901 | switch (ios->bus_width) { |
| 889 | case MMC_BUS_WIDTH_1: | 902 | case MMC_BUS_WIDTH_1: |
| 890 | sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0); | 903 | sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0); |
| @@ -988,7 +1001,9 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
| 988 | if (!mmc) | 1001 | if (!mmc) |
| 989 | return -ENOMEM; | 1002 | return -ENOMEM; |
| 990 | 1003 | ||
| 991 | mmc_of_parse(mmc); | 1004 | ret = mmc_of_parse(mmc); |
| 1005 | if (ret < 0) | ||
| 1006 | goto host_free; | ||
| 992 | 1007 | ||
| 993 | pdata->dev = &pdev->dev; | 1008 | pdata->dev = &pdev->dev; |
| 994 | _host = mmc_priv(mmc); | 1009 | _host = mmc_priv(mmc); |
| @@ -1025,7 +1040,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
| 1025 | mmc->caps & MMC_CAP_NONREMOVABLE || | 1040 | mmc->caps & MMC_CAP_NONREMOVABLE || |
| 1026 | mmc->slot.cd_irq >= 0); | 1041 | mmc->slot.cd_irq >= 0); |
| 1027 | 1042 | ||
| 1028 | _host->power = false; | 1043 | _host->power = TMIO_MMC_OFF_STOP; |
| 1029 | pm_runtime_enable(&pdev->dev); | 1044 | pm_runtime_enable(&pdev->dev); |
| 1030 | ret = pm_runtime_resume(&pdev->dev); | 1045 | ret = pm_runtime_resume(&pdev->dev); |
| 1031 | if (ret < 0) | 1046 | if (ret < 0) |
| @@ -1154,10 +1169,10 @@ int tmio_mmc_host_resume(struct device *dev) | |||
| 1154 | struct mmc_host *mmc = dev_get_drvdata(dev); | 1169 | struct mmc_host *mmc = dev_get_drvdata(dev); |
| 1155 | struct tmio_mmc_host *host = mmc_priv(mmc); | 1170 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 1156 | 1171 | ||
| 1157 | tmio_mmc_reset(host); | ||
| 1158 | tmio_mmc_enable_dma(host, true); | 1172 | tmio_mmc_enable_dma(host, true); |
| 1159 | 1173 | ||
| 1160 | /* The MMC core will perform the complete set up */ | 1174 | /* The MMC core will perform the complete set up */ |
| 1175 | host->resuming = true; | ||
| 1161 | return mmc_resume_host(mmc); | 1176 | return mmc_resume_host(mmc); |
| 1162 | } | 1177 | } |
| 1163 | EXPORT_SYMBOL(tmio_mmc_host_resume); | 1178 | EXPORT_SYMBOL(tmio_mmc_host_resume); |
| @@ -1175,7 +1190,6 @@ int tmio_mmc_host_runtime_resume(struct device *dev) | |||
| 1175 | struct mmc_host *mmc = dev_get_drvdata(dev); | 1190 | struct mmc_host *mmc = dev_get_drvdata(dev); |
| 1176 | struct tmio_mmc_host *host = mmc_priv(mmc); | 1191 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 1177 | 1192 | ||
| 1178 | tmio_mmc_reset(host); | ||
| 1179 | tmio_mmc_enable_dma(host, true); | 1193 | tmio_mmc_enable_dma(host, true); |
| 1180 | 1194 | ||
| 1181 | return 0; | 1195 | return 0; |
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index 442f5766ffca..34231d5168fc 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c | |||
| @@ -927,8 +927,6 @@ static int wmt_mci_remove(struct platform_device *pdev) | |||
| 927 | 927 | ||
| 928 | mmc_free_host(mmc); | 928 | mmc_free_host(mmc); |
| 929 | 929 | ||
| 930 | platform_set_drvdata(pdev, NULL); | ||
| 931 | |||
| 932 | dev_info(&pdev->dev, "WMT MCI device removed\n"); | 930 | dev_info(&pdev->dev, "WMT MCI device removed\n"); |
| 933 | 931 | ||
| 934 | return 0; | 932 | return 0; |
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index 99bf3e665997..ce3511326f80 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h | |||
| @@ -81,10 +81,15 @@ int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base); | |||
| 81 | void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state); | 81 | void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state); |
| 82 | void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state); | 82 | void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state); |
| 83 | 83 | ||
| 84 | struct dma_chan; | ||
| 85 | |||
| 84 | struct tmio_mmc_dma { | 86 | struct tmio_mmc_dma { |
| 85 | void *chan_priv_tx; | 87 | void *chan_priv_tx; |
| 86 | void *chan_priv_rx; | 88 | void *chan_priv_rx; |
| 89 | int slave_id_tx; | ||
| 90 | int slave_id_rx; | ||
| 87 | int alignment_shift; | 91 | int alignment_shift; |
| 92 | bool (*filter)(struct dma_chan *chan, void *arg); | ||
| 88 | }; | 93 | }; |
| 89 | 94 | ||
| 90 | struct tmio_mmc_host; | 95 | struct tmio_mmc_host; |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index f31725ba49f3..842de3e21e70 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
| @@ -94,7 +94,11 @@ struct mmc_ext_csd { | |||
| 94 | u8 raw_ext_csd_structure; /* 194 */ | 94 | u8 raw_ext_csd_structure; /* 194 */ |
| 95 | u8 raw_card_type; /* 196 */ | 95 | u8 raw_card_type; /* 196 */ |
| 96 | u8 out_of_int_time; /* 198 */ | 96 | u8 out_of_int_time; /* 198 */ |
| 97 | u8 raw_s_a_timeout; /* 217 */ | 97 | u8 raw_pwr_cl_52_195; /* 200 */ |
| 98 | u8 raw_pwr_cl_26_195; /* 201 */ | ||
| 99 | u8 raw_pwr_cl_52_360; /* 202 */ | ||
| 100 | u8 raw_pwr_cl_26_360; /* 203 */ | ||
| 101 | u8 raw_s_a_timeout; /* 217 */ | ||
| 98 | u8 raw_hc_erase_gap_size; /* 221 */ | 102 | u8 raw_hc_erase_gap_size; /* 221 */ |
| 99 | u8 raw_erase_timeout_mult; /* 223 */ | 103 | u8 raw_erase_timeout_mult; /* 223 */ |
| 100 | u8 raw_hc_erase_grp_size; /* 224 */ | 104 | u8 raw_hc_erase_grp_size; /* 224 */ |
| @@ -102,6 +106,10 @@ struct mmc_ext_csd { | |||
| 102 | u8 raw_sec_erase_mult; /* 230 */ | 106 | u8 raw_sec_erase_mult; /* 230 */ |
| 103 | u8 raw_sec_feature_support;/* 231 */ | 107 | u8 raw_sec_feature_support;/* 231 */ |
| 104 | u8 raw_trim_mult; /* 232 */ | 108 | u8 raw_trim_mult; /* 232 */ |
| 109 | u8 raw_pwr_cl_200_195; /* 236 */ | ||
| 110 | u8 raw_pwr_cl_200_360; /* 237 */ | ||
| 111 | u8 raw_pwr_cl_ddr_52_195; /* 238 */ | ||
| 112 | u8 raw_pwr_cl_ddr_52_360; /* 239 */ | ||
| 105 | u8 raw_bkops_status; /* 246 */ | 113 | u8 raw_bkops_status; /* 246 */ |
| 106 | u8 raw_sectors[4]; /* 212 - 4 bytes */ | 114 | u8 raw_sectors[4]; /* 212 - 4 bytes */ |
| 107 | 115 | ||
| @@ -512,6 +520,7 @@ struct mmc_driver { | |||
| 512 | void (*remove)(struct mmc_card *); | 520 | void (*remove)(struct mmc_card *); |
| 513 | int (*suspend)(struct mmc_card *); | 521 | int (*suspend)(struct mmc_card *); |
| 514 | int (*resume)(struct mmc_card *); | 522 | int (*resume)(struct mmc_card *); |
| 523 | void (*shutdown)(struct mmc_card *); | ||
| 515 | }; | 524 | }; |
| 516 | 525 | ||
| 517 | extern int mmc_register_driver(struct mmc_driver *); | 526 | extern int mmc_register_driver(struct mmc_driver *); |
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 39613b9a6fc5..443243b241d5 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h | |||
| @@ -96,6 +96,8 @@ struct mmc_command { | |||
| 96 | */ | 96 | */ |
| 97 | 97 | ||
| 98 | unsigned int cmd_timeout_ms; /* in milliseconds */ | 98 | unsigned int cmd_timeout_ms; /* in milliseconds */ |
| 99 | /* Set this flag only for blocking sanitize request */ | ||
| 100 | bool sanitize_busy; | ||
| 99 | 101 | ||
| 100 | struct mmc_data *data; /* data segment associated with cmd */ | 102 | struct mmc_data *data; /* data segment associated with cmd */ |
| 101 | struct mmc_request *mrq; /* associated request */ | 103 | struct mmc_request *mrq; /* associated request */ |
| @@ -188,6 +190,9 @@ extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); | |||
| 188 | extern void mmc_release_host(struct mmc_host *host); | 190 | extern void mmc_release_host(struct mmc_host *host); |
| 189 | extern int mmc_try_claim_host(struct mmc_host *host); | 191 | extern int mmc_try_claim_host(struct mmc_host *host); |
| 190 | 192 | ||
| 193 | extern void mmc_get_card(struct mmc_card *card); | ||
| 194 | extern void mmc_put_card(struct mmc_card *card); | ||
| 195 | |||
| 191 | extern int mmc_flush_cache(struct mmc_card *); | 196 | extern int mmc_flush_cache(struct mmc_card *); |
| 192 | 197 | ||
| 193 | extern int mmc_detect_card_removed(struct mmc_host *host); | 198 | extern int mmc_detect_card_removed(struct mmc_host *host); |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index e326ae2882a0..3b0c33ae13e1 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
| @@ -239,7 +239,7 @@ struct mmc_host { | |||
| 239 | #define MMC_CAP_SPI (1 << 4) /* Talks only SPI protocols */ | 239 | #define MMC_CAP_SPI (1 << 4) /* Talks only SPI protocols */ |
| 240 | #define MMC_CAP_NEEDS_POLL (1 << 5) /* Needs polling for card-detection */ | 240 | #define MMC_CAP_NEEDS_POLL (1 << 5) /* Needs polling for card-detection */ |
| 241 | #define MMC_CAP_8_BIT_DATA (1 << 6) /* Can the host do 8 bit transfers */ | 241 | #define MMC_CAP_8_BIT_DATA (1 << 6) /* Can the host do 8 bit transfers */ |
| 242 | 242 | #define MMC_CAP_AGGRESSIVE_PM (1 << 7) /* Suspend (e)MMC/SD at idle */ | |
| 243 | #define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ | 243 | #define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ |
| 244 | #define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ | 244 | #define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ |
| 245 | #define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */ | 245 | #define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */ |
| @@ -264,7 +264,7 @@ struct mmc_host { | |||
| 264 | 264 | ||
| 265 | #define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */ | 265 | #define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */ |
| 266 | #define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */ | 266 | #define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */ |
| 267 | #define MMC_CAP2_POWEROFF_NOTIFY (1 << 2) /* Notify poweroff supported */ | 267 | #define MMC_CAP2_FULL_PWR_CYCLE (1 << 2) /* Can do full power cycle */ |
| 268 | #define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock reads don't work */ | 268 | #define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock reads don't work */ |
| 269 | #define MMC_CAP2_NO_SLEEP_CMD (1 << 4) /* Don't allow sleep command */ | 269 | #define MMC_CAP2_NO_SLEEP_CMD (1 << 4) /* Don't allow sleep command */ |
| 270 | #define MMC_CAP2_HS200_1_8V_SDR (1 << 5) /* can support */ | 270 | #define MMC_CAP2_HS200_1_8V_SDR (1 << 5) /* can support */ |
| @@ -272,7 +272,6 @@ struct mmc_host { | |||
| 272 | #define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \ | 272 | #define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \ |
| 273 | MMC_CAP2_HS200_1_2V_SDR) | 273 | MMC_CAP2_HS200_1_2V_SDR) |
| 274 | #define MMC_CAP2_BROKEN_VOLTAGE (1 << 7) /* Use the broken voltage */ | 274 | #define MMC_CAP2_BROKEN_VOLTAGE (1 << 7) /* Use the broken voltage */ |
| 275 | #define MMC_CAP2_DETECT_ON_ERR (1 << 8) /* On I/O err check card removal */ | ||
| 276 | #define MMC_CAP2_HC_ERASE_SZ (1 << 9) /* High-capacity erase size */ | 275 | #define MMC_CAP2_HC_ERASE_SZ (1 << 9) /* High-capacity erase size */ |
| 277 | #define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */ | 276 | #define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */ |
| 278 | #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ | 277 | #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ |
| @@ -281,6 +280,7 @@ struct mmc_host { | |||
| 281 | #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ | 280 | #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ |
| 282 | MMC_CAP2_PACKED_WR) | 281 | MMC_CAP2_PACKED_WR) |
| 283 | #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ | 282 | #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ |
| 283 | #define MMC_CAP2_SANITIZE (1 << 15) /* Support Sanitize */ | ||
| 284 | 284 | ||
| 285 | mmc_pm_flag_t pm_caps; /* supported pm features */ | 285 | mmc_pm_flag_t pm_caps; /* supported pm features */ |
| 286 | 286 | ||
| @@ -369,7 +369,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *); | |||
| 369 | int mmc_add_host(struct mmc_host *); | 369 | int mmc_add_host(struct mmc_host *); |
| 370 | void mmc_remove_host(struct mmc_host *); | 370 | void mmc_remove_host(struct mmc_host *); |
| 371 | void mmc_free_host(struct mmc_host *); | 371 | void mmc_free_host(struct mmc_host *); |
| 372 | void mmc_of_parse(struct mmc_host *host); | 372 | int mmc_of_parse(struct mmc_host *host); |
| 373 | 373 | ||
| 374 | static inline void *mmc_priv(struct mmc_host *host) | 374 | static inline void *mmc_priv(struct mmc_host *host) |
| 375 | { | 375 | { |
| @@ -425,10 +425,6 @@ static inline int mmc_regulator_get_supply(struct mmc_host *mmc) | |||
| 425 | } | 425 | } |
| 426 | #endif | 426 | #endif |
| 427 | 427 | ||
| 428 | int mmc_card_awake(struct mmc_host *host); | ||
| 429 | int mmc_card_sleep(struct mmc_host *host); | ||
| 430 | int mmc_card_can_sleep(struct mmc_host *host); | ||
| 431 | |||
| 432 | int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); | 428 | int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); |
| 433 | 429 | ||
| 434 | /* Module parameter */ | 430 | /* Module parameter */ |
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index b838ffc49e4a..e3c6a74d980a 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h | |||
| @@ -95,6 +95,9 @@ struct sdhci_host { | |||
| 95 | /* The system physically doesn't support 1.8v, even if the host does */ | 95 | /* The system physically doesn't support 1.8v, even if the host does */ |
| 96 | #define SDHCI_QUIRK2_NO_1_8_V (1<<2) | 96 | #define SDHCI_QUIRK2_NO_1_8_V (1<<2) |
| 97 | #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3) | 97 | #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3) |
| 98 | #define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4) | ||
| 99 | /* Controller has a non-standard host control register */ | ||
| 100 | #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) | ||
| 98 | 101 | ||
| 99 | int irq; /* Device IRQ */ | 102 | int irq; /* Device IRQ */ |
| 100 | void __iomem *ioaddr; /* Mapped address */ | 103 | void __iomem *ioaddr; /* Mapped address */ |
| @@ -126,7 +129,7 @@ struct sdhci_host { | |||
| 126 | #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ | 129 | #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ |
| 127 | #define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */ | 130 | #define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */ |
| 128 | #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ | 131 | #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ |
| 129 | #define SDHCI_HS200_NEEDS_TUNING (1<<10) /* HS200 needs tuning */ | 132 | #define SDHCI_SDR104_NEEDS_TUNING (1<<10) /* SDR104/HS200 needs tuning */ |
| 130 | #define SDHCI_USING_RETUNING_TIMER (1<<11) /* Host is using a retuning timer for the card */ | 133 | #define SDHCI_USING_RETUNING_TIMER (1<<11) /* Host is using a retuning timer for the card */ |
| 131 | 134 | ||
| 132 | unsigned int version; /* SDHCI spec. version */ | 135 | unsigned int version; /* SDHCI spec. version */ |
| @@ -139,6 +142,7 @@ struct sdhci_host { | |||
| 139 | u8 pwr; /* Current voltage */ | 142 | u8 pwr; /* Current voltage */ |
| 140 | 143 | ||
| 141 | bool runtime_suspended; /* Host is runtime suspended */ | 144 | bool runtime_suspended; /* Host is runtime suspended */ |
| 145 | bool bus_on; /* Bus power prevents runtime suspend */ | ||
| 142 | 146 | ||
| 143 | struct mmc_request *mrq; /* Current request */ | 147 | struct mmc_request *mrq; /* Current request */ |
| 144 | struct mmc_command *cmd; /* Current command */ | 148 | struct mmc_command *cmd; /* Current command */ |
diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h index b4a0521ce411..d44912d81578 100644 --- a/include/linux/platform_data/mmc-esdhc-imx.h +++ b/include/linux/platform_data/mmc-esdhc-imx.h | |||
| @@ -40,5 +40,6 @@ struct esdhc_platform_data { | |||
| 40 | enum wp_types wp_type; | 40 | enum wp_types wp_type; |
| 41 | enum cd_types cd_type; | 41 | enum cd_types cd_type; |
| 42 | int max_bus_width; | 42 | int max_bus_width; |
| 43 | unsigned int f_max; | ||
| 43 | }; | 44 | }; |
| 44 | #endif /* __ASM_ARCH_IMX_ESDHC_H */ | 45 | #endif /* __ASM_ARCH_IMX_ESDHC_H */ |
