diff options
Diffstat (limited to 'drivers/mmc')
38 files changed, 770 insertions, 513 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 5bab73b91c20..e12a03cc2a6e 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -1932,8 +1932,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
1932 | } | 1932 | } |
1933 | 1933 | ||
1934 | out: | 1934 | out: |
1935 | if (!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) | 1935 | if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || |
1936 | /* release host only when there are no more requests */ | 1936 | (req && (req->cmd_flags & MMC_REQ_SPECIAL_MASK))) |
1937 | /* | ||
1938 | * Release host when there are no more requests | ||
1939 | * and after special request(discard, flush) is done. | ||
1940 | * In case sepecial request, there is no reentry to | ||
1941 | * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'. | ||
1942 | */ | ||
1937 | mmc_release_host(card->host); | 1943 | mmc_release_host(card->host); |
1938 | return ret; | 1944 | return ret; |
1939 | } | 1945 | } |
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index fa4e44ee7961..9447a0e970d1 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c | |||
@@ -22,9 +22,6 @@ | |||
22 | 22 | ||
23 | #define MMC_QUEUE_BOUNCESZ 65536 | 23 | #define MMC_QUEUE_BOUNCESZ 65536 |
24 | 24 | ||
25 | |||
26 | #define MMC_REQ_SPECIAL_MASK (REQ_DISCARD | REQ_FLUSH) | ||
27 | |||
28 | /* | 25 | /* |
29 | * Prepare a MMC request. This just filters out odd stuff. | 26 | * Prepare a MMC request. This just filters out odd stuff. |
30 | */ | 27 | */ |
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index 031bf6376c99..5752d50049a3 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef MMC_QUEUE_H | 1 | #ifndef MMC_QUEUE_H |
2 | #define MMC_QUEUE_H | 2 | #define MMC_QUEUE_H |
3 | 3 | ||
4 | #define MMC_REQ_SPECIAL_MASK (REQ_DISCARD | REQ_FLUSH) | ||
5 | |||
4 | struct request; | 6 | struct request; |
5 | struct task_struct; | 7 | struct task_struct; |
6 | 8 | ||
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 9290bb51a06a..c40396f23202 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -2289,6 +2289,19 @@ int _mmc_detect_card_removed(struct mmc_host *host) | |||
2289 | return 1; | 2289 | return 1; |
2290 | 2290 | ||
2291 | ret = host->bus_ops->alive(host); | 2291 | ret = host->bus_ops->alive(host); |
2292 | |||
2293 | /* | ||
2294 | * Card detect status and alive check may be out of sync if card is | ||
2295 | * removed slowly, when card detect switch changes while card/slot | ||
2296 | * pads are still contacted in hardware (refer to "SD Card Mechanical | ||
2297 | * Addendum, Appendix C: Card Detection Switch"). So reschedule a | ||
2298 | * detect work 200ms later for this case. | ||
2299 | */ | ||
2300 | if (!ret && host->ops->get_cd && !host->ops->get_cd(host)) { | ||
2301 | mmc_detect_change(host, msecs_to_jiffies(200)); | ||
2302 | pr_debug("%s: card removed too slowly\n", mmc_hostname(host)); | ||
2303 | } | ||
2304 | |||
2292 | if (ret) { | 2305 | if (ret) { |
2293 | mmc_card_set_removed(host->card); | 2306 | mmc_card_set_removed(host->card); |
2294 | pr_debug("%s: card remove detected\n", mmc_hostname(host)); | 2307 | pr_debug("%s: card remove detected\n", mmc_hostname(host)); |
@@ -2403,7 +2416,10 @@ void mmc_start_host(struct mmc_host *host) | |||
2403 | { | 2416 | { |
2404 | host->f_init = max(freqs[0], host->f_min); | 2417 | host->f_init = max(freqs[0], host->f_min); |
2405 | host->rescan_disable = 0; | 2418 | host->rescan_disable = 0; |
2406 | mmc_power_up(host); | 2419 | if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP) |
2420 | mmc_power_off(host); | ||
2421 | else | ||
2422 | mmc_power_up(host); | ||
2407 | mmc_detect_change(host, 0); | 2423 | mmc_detect_change(host, 0); |
2408 | } | 2424 | } |
2409 | 2425 | ||
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index c8f3d6e0684e..0cbd1effe960 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -96,6 +96,7 @@ static int mmc_decode_cid(struct mmc_card *card) | |||
96 | card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); | 96 | card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); |
97 | card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); | 97 | card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); |
98 | card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); | 98 | card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); |
99 | card->cid.prv = UNSTUFF_BITS(resp, 48, 8); | ||
99 | card->cid.serial = UNSTUFF_BITS(resp, 16, 32); | 100 | card->cid.serial = UNSTUFF_BITS(resp, 16, 32); |
100 | card->cid.month = UNSTUFF_BITS(resp, 12, 4); | 101 | card->cid.month = UNSTUFF_BITS(resp, 12, 4); |
101 | card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; | 102 | card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; |
@@ -368,13 +369,13 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
368 | ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; | 369 | ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; |
369 | card->ext_csd.raw_trim_mult = | 370 | card->ext_csd.raw_trim_mult = |
370 | ext_csd[EXT_CSD_TRIM_MULT]; | 371 | ext_csd[EXT_CSD_TRIM_MULT]; |
372 | card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; | ||
371 | if (card->ext_csd.rev >= 4) { | 373 | if (card->ext_csd.rev >= 4) { |
372 | /* | 374 | /* |
373 | * Enhanced area feature support -- check whether the eMMC | 375 | * Enhanced area feature support -- check whether the eMMC |
374 | * card has the Enhanced area enabled. If so, export enhanced | 376 | * card has the Enhanced area enabled. If so, export enhanced |
375 | * area offset and size to user by adding sysfs interface. | 377 | * area offset and size to user by adding sysfs interface. |
376 | */ | 378 | */ |
377 | card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; | ||
378 | if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && | 379 | if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && |
379 | (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { | 380 | (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { |
380 | hc_erase_grp_sz = | 381 | hc_erase_grp_sz = |
@@ -627,6 +628,7 @@ MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); | |||
627 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); | 628 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); |
628 | MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); | 629 | MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); |
629 | MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); | 630 | MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); |
631 | MMC_DEV_ATTR(prv, "0x%x\n", card->cid.prv); | ||
630 | MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); | 632 | MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); |
631 | MMC_DEV_ATTR(enhanced_area_offset, "%llu\n", | 633 | MMC_DEV_ATTR(enhanced_area_offset, "%llu\n", |
632 | card->ext_csd.enhanced_area_offset); | 634 | card->ext_csd.enhanced_area_offset); |
@@ -645,6 +647,7 @@ static struct attribute *mmc_std_attrs[] = { | |||
645 | &dev_attr_manfid.attr, | 647 | &dev_attr_manfid.attr, |
646 | &dev_attr_name.attr, | 648 | &dev_attr_name.attr, |
647 | &dev_attr_oemid.attr, | 649 | &dev_attr_oemid.attr, |
650 | &dev_attr_prv.attr, | ||
648 | &dev_attr_serial.attr, | 651 | &dev_attr_serial.attr, |
649 | &dev_attr_enhanced_area_offset.attr, | 652 | &dev_attr_enhanced_area_offset.attr, |
650 | &dev_attr_enhanced_area_size.attr, | 653 | &dev_attr_enhanced_area_size.attr, |
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index aa0719a4dfd1..6889a821c1da 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -861,8 +861,10 @@ static void mmc_sdio_detect(struct mmc_host *host) | |||
861 | /* Make sure card is powered before detecting it */ | 861 | /* Make sure card is powered before detecting it */ |
862 | if (host->caps & MMC_CAP_POWER_OFF_CARD) { | 862 | if (host->caps & MMC_CAP_POWER_OFF_CARD) { |
863 | err = pm_runtime_get_sync(&host->card->dev); | 863 | err = pm_runtime_get_sync(&host->card->dev); |
864 | if (err < 0) | 864 | if (err < 0) { |
865 | pm_runtime_put_noidle(&host->card->dev); | ||
865 | goto out; | 866 | goto out; |
867 | } | ||
866 | } | 868 | } |
867 | 869 | ||
868 | mmc_claim_host(host); | 870 | mmc_claim_host(host); |
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 5e57048e2c1d..546c67c2bbbf 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/export.h> | 16 | #include <linux/export.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/pm_runtime.h> | 18 | #include <linux/pm_runtime.h> |
19 | #include <linux/acpi.h> | ||
19 | 20 | ||
20 | #include <linux/mmc/card.h> | 21 | #include <linux/mmc/card.h> |
21 | #include <linux/mmc/host.h> | 22 | #include <linux/mmc/host.h> |
@@ -137,7 +138,7 @@ static int sdio_bus_probe(struct device *dev) | |||
137 | if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) { | 138 | if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) { |
138 | ret = pm_runtime_get_sync(dev); | 139 | ret = pm_runtime_get_sync(dev); |
139 | if (ret < 0) | 140 | if (ret < 0) |
140 | goto out; | 141 | goto disable_runtimepm; |
141 | } | 142 | } |
142 | 143 | ||
143 | /* Set the default block size so the driver is sure it's something | 144 | /* Set the default block size so the driver is sure it's something |
@@ -157,7 +158,6 @@ static int sdio_bus_probe(struct device *dev) | |||
157 | disable_runtimepm: | 158 | disable_runtimepm: |
158 | if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) | 159 | if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) |
159 | pm_runtime_put_noidle(dev); | 160 | pm_runtime_put_noidle(dev); |
160 | out: | ||
161 | return ret; | 161 | return ret; |
162 | } | 162 | } |
163 | 163 | ||
@@ -299,6 +299,19 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card) | |||
299 | return func; | 299 | return func; |
300 | } | 300 | } |
301 | 301 | ||
302 | #ifdef CONFIG_ACPI | ||
303 | static void sdio_acpi_set_handle(struct sdio_func *func) | ||
304 | { | ||
305 | struct mmc_host *host = func->card->host; | ||
306 | u64 addr = (host->slotno << 16) | func->num; | ||
307 | |||
308 | ACPI_HANDLE_SET(&func->dev, | ||
309 | acpi_get_child(ACPI_HANDLE(host->parent), addr)); | ||
310 | } | ||
311 | #else | ||
312 | static inline void sdio_acpi_set_handle(struct sdio_func *func) {} | ||
313 | #endif | ||
314 | |||
302 | /* | 315 | /* |
303 | * Register a new SDIO function with the driver model. | 316 | * Register a new SDIO function with the driver model. |
304 | */ | 317 | */ |
@@ -308,9 +321,12 @@ int sdio_add_func(struct sdio_func *func) | |||
308 | 321 | ||
309 | dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num); | 322 | dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num); |
310 | 323 | ||
324 | sdio_acpi_set_handle(func); | ||
311 | ret = device_add(&func->dev); | 325 | ret = device_add(&func->dev); |
312 | if (ret == 0) | 326 | if (ret == 0) { |
313 | sdio_func_set_present(func); | 327 | sdio_func_set_present(func); |
328 | acpi_dev_pm_attach(&func->dev, false); | ||
329 | } | ||
314 | 330 | ||
315 | return ret; | 331 | return ret; |
316 | } | 332 | } |
@@ -326,6 +342,7 @@ void sdio_remove_func(struct sdio_func *func) | |||
326 | if (!sdio_func_present(func)) | 342 | if (!sdio_func_present(func)) |
327 | return; | 343 | return; |
328 | 344 | ||
345 | acpi_dev_pm_detach(&func->dev, false); | ||
329 | device_del(&func->dev); | 346 | device_del(&func->dev); |
330 | put_device(&func->dev); | 347 | put_device(&func->dev); |
331 | } | 348 | } |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index d88219e1d86e..9ab8f8dee942 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -190,6 +190,17 @@ config MMC_SDHCI_S3C | |||
190 | 190 | ||
191 | If unsure, say N. | 191 | If unsure, say N. |
192 | 192 | ||
193 | config MMC_SDHCI_SIRF | ||
194 | tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs" | ||
195 | depends on ARCH_SIRF | ||
196 | depends on MMC_SDHCI_PLTFM | ||
197 | help | ||
198 | This selects the SDHCI support for SiRF System-on-Chip devices. | ||
199 | |||
200 | If you have a controller with this interface, say Y or M here. | ||
201 | |||
202 | If unsure, say N. | ||
203 | |||
193 | config MMC_SDHCI_PXAV3 | 204 | config MMC_SDHCI_PXAV3 |
194 | tristate "Marvell MMP2 SD Host Controller support (PXAV3)" | 205 | tristate "Marvell MMP2 SD Host Controller support (PXAV3)" |
195 | depends on CLKDEV_LOOKUP | 206 | depends on CLKDEV_LOOKUP |
@@ -300,16 +311,6 @@ config MMC_ATMELMCI | |||
300 | 311 | ||
301 | If unsure, say N. | 312 | If unsure, say N. |
302 | 313 | ||
303 | config MMC_ATMELMCI_DMA | ||
304 | bool "Atmel MCI DMA support" | ||
305 | depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE | ||
306 | help | ||
307 | Say Y here to have the Atmel MCI driver use a DMA engine to | ||
308 | do data transfers and thus increase the throughput and | ||
309 | reduce the CPU utilization. | ||
310 | |||
311 | If unsure, say N. | ||
312 | |||
313 | config MMC_MSM | 314 | config MMC_MSM |
314 | tristate "Qualcomm SDCC Controller Support" | 315 | tristate "Qualcomm SDCC Controller Support" |
315 | depends on MMC && ARCH_MSM | 316 | depends on MMC && ARCH_MSM |
@@ -319,12 +320,12 @@ config MMC_MSM | |||
319 | support for SDIO devices. | 320 | support for SDIO devices. |
320 | 321 | ||
321 | config MMC_MXC | 322 | config MMC_MXC |
322 | tristate "Freescale i.MX21/27/31 Multimedia Card Interface support" | 323 | tristate "Freescale i.MX21/27/31 or MPC512x Multimedia Card support" |
323 | depends on ARCH_MXC | 324 | depends on ARCH_MXC || PPC_MPC512x |
324 | help | 325 | help |
325 | This selects the Freescale i.MX21, i.MX27 and i.MX31 Multimedia card | 326 | This selects the Freescale i.MX21, i.MX27, i.MX31 or MPC512x |
326 | Interface. If you have a i.MX platform with a Multimedia Card slot, | 327 | Multimedia Card Interface. If you have an i.MX or MPC512x platform |
327 | say Y or M here. | 328 | with a Multimedia Card slot, say Y or M here. |
328 | 329 | ||
329 | If unsure, say N. | 330 | If unsure, say N. |
330 | 331 | ||
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index c380e3cf0a3b..cd3228075553 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_MMC_SDHCI_ACPI) += sdhci-acpi.o | |||
13 | obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o | 13 | obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o |
14 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o | 14 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o |
15 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o | 15 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o |
16 | obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o | ||
16 | obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o | 17 | obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o |
17 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 18 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
18 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o | 19 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o |
diff --git a/drivers/mmc/host/android-goldfish.c b/drivers/mmc/host/android-goldfish.c index ef3aef0f376d..7780c14704c4 100644 --- a/drivers/mmc/host/android-goldfish.c +++ b/drivers/mmc/host/android-goldfish.c | |||
@@ -476,7 +476,7 @@ static int goldfish_mmc_probe(struct platform_device *pdev) | |||
476 | host->mmc = mmc; | 476 | host->mmc = mmc; |
477 | 477 | ||
478 | pr_err("mmc: Mapping %lX to %lX\n", (long)res->start, (long)res->end); | 478 | pr_err("mmc: Mapping %lX to %lX\n", (long)res->start, (long)res->end); |
479 | host->reg_base = ioremap(res->start, res->end - res->start + 1); | 479 | host->reg_base = ioremap(res->start, resource_size(res)); |
480 | if (host->reg_base == NULL) { | 480 | if (host->reg_base == NULL) { |
481 | ret = -ENOMEM; | 481 | ret = -ENOMEM; |
482 | goto ioremap_failed; | 482 | goto ioremap_failed; |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 722af1de7967..e75774f72606 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -178,6 +178,7 @@ struct atmel_mci { | |||
178 | void __iomem *regs; | 178 | void __iomem *regs; |
179 | 179 | ||
180 | struct scatterlist *sg; | 180 | struct scatterlist *sg; |
181 | unsigned int sg_len; | ||
181 | unsigned int pio_offset; | 182 | unsigned int pio_offset; |
182 | unsigned int *buffer; | 183 | unsigned int *buffer; |
183 | unsigned int buf_size; | 184 | unsigned int buf_size; |
@@ -892,6 +893,7 @@ static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data) | |||
892 | data->error = -EINPROGRESS; | 893 | data->error = -EINPROGRESS; |
893 | 894 | ||
894 | host->sg = data->sg; | 895 | host->sg = data->sg; |
896 | host->sg_len = data->sg_len; | ||
895 | host->data = data; | 897 | host->data = data; |
896 | host->data_chan = NULL; | 898 | host->data_chan = NULL; |
897 | 899 | ||
@@ -1826,7 +1828,8 @@ static void atmci_read_data_pio(struct atmel_mci *host) | |||
1826 | if (offset == sg->length) { | 1828 | if (offset == sg->length) { |
1827 | flush_dcache_page(sg_page(sg)); | 1829 | flush_dcache_page(sg_page(sg)); |
1828 | host->sg = sg = sg_next(sg); | 1830 | host->sg = sg = sg_next(sg); |
1829 | if (!sg) | 1831 | host->sg_len--; |
1832 | if (!sg || !host->sg_len) | ||
1830 | goto done; | 1833 | goto done; |
1831 | 1834 | ||
1832 | offset = 0; | 1835 | offset = 0; |
@@ -1839,7 +1842,8 @@ static void atmci_read_data_pio(struct atmel_mci *host) | |||
1839 | 1842 | ||
1840 | flush_dcache_page(sg_page(sg)); | 1843 | flush_dcache_page(sg_page(sg)); |
1841 | host->sg = sg = sg_next(sg); | 1844 | host->sg = sg = sg_next(sg); |
1842 | if (!sg) | 1845 | host->sg_len--; |
1846 | if (!sg || !host->sg_len) | ||
1843 | goto done; | 1847 | goto done; |
1844 | 1848 | ||
1845 | offset = 4 - remaining; | 1849 | offset = 4 - remaining; |
@@ -1890,7 +1894,8 @@ static void atmci_write_data_pio(struct atmel_mci *host) | |||
1890 | nbytes += 4; | 1894 | nbytes += 4; |
1891 | if (offset == sg->length) { | 1895 | if (offset == sg->length) { |
1892 | host->sg = sg = sg_next(sg); | 1896 | host->sg = sg = sg_next(sg); |
1893 | if (!sg) | 1897 | host->sg_len--; |
1898 | if (!sg || !host->sg_len) | ||
1894 | goto done; | 1899 | goto done; |
1895 | 1900 | ||
1896 | offset = 0; | 1901 | offset = 0; |
@@ -1904,7 +1909,8 @@ static void atmci_write_data_pio(struct atmel_mci *host) | |||
1904 | nbytes += remaining; | 1909 | nbytes += remaining; |
1905 | 1910 | ||
1906 | host->sg = sg = sg_next(sg); | 1911 | host->sg = sg = sg_next(sg); |
1907 | if (!sg) { | 1912 | host->sg_len--; |
1913 | if (!sg || !host->sg_len) { | ||
1908 | atmci_writel(host, ATMCI_TDR, value); | 1914 | atmci_writel(host, ATMCI_TDR, value); |
1909 | goto done; | 1915 | goto done; |
1910 | } | 1916 | } |
@@ -2487,10 +2493,8 @@ static int __exit atmci_remove(struct platform_device *pdev) | |||
2487 | atmci_readl(host, ATMCI_SR); | 2493 | atmci_readl(host, ATMCI_SR); |
2488 | clk_disable(host->mck); | 2494 | clk_disable(host->mck); |
2489 | 2495 | ||
2490 | #ifdef CONFIG_MMC_ATMELMCI_DMA | ||
2491 | if (host->dma.chan) | 2496 | if (host->dma.chan) |
2492 | dma_release_channel(host->dma.chan); | 2497 | dma_release_channel(host->dma.chan); |
2493 | #endif | ||
2494 | 2498 | ||
2495 | free_irq(platform_get_irq(pdev, 0), host); | 2499 | free_irq(platform_get_irq(pdev, 0), host); |
2496 | iounmap(host->regs); | 2500 | iounmap(host->regs); |
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index f8a96d652e9e..3946a0eb3a03 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c | |||
@@ -1264,13 +1264,15 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) | |||
1264 | 1264 | ||
1265 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 1265 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
1266 | if (!r) | 1266 | if (!r) |
1267 | goto out; | 1267 | dev_warn(&pdev->dev, "RX DMA resource not specified\n"); |
1268 | host->rxdma = r->start; | 1268 | else |
1269 | host->rxdma = r->start; | ||
1269 | 1270 | ||
1270 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 1271 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
1271 | if (!r) | 1272 | if (!r) |
1272 | goto out; | 1273 | dev_warn(&pdev->dev, "TX DMA resource not specified\n"); |
1273 | host->txdma = r->start; | 1274 | else |
1275 | host->txdma = r->start; | ||
1274 | 1276 | ||
1275 | host->mem_res = mem; | 1277 | host->mem_res = mem; |
1276 | host->base = ioremap(mem->start, mem_size); | 1278 | host->base = ioremap(mem->start, mem_size); |
@@ -1488,18 +1490,7 @@ static struct platform_driver davinci_mmcsd_driver = { | |||
1488 | .id_table = davinci_mmc_devtype, | 1490 | .id_table = davinci_mmc_devtype, |
1489 | }; | 1491 | }; |
1490 | 1492 | ||
1491 | static int __init davinci_mmcsd_init(void) | 1493 | module_platform_driver_probe(davinci_mmcsd_driver, davinci_mmcsd_probe); |
1492 | { | ||
1493 | return platform_driver_probe(&davinci_mmcsd_driver, | ||
1494 | davinci_mmcsd_probe); | ||
1495 | } | ||
1496 | module_init(davinci_mmcsd_init); | ||
1497 | |||
1498 | static void __exit davinci_mmcsd_exit(void) | ||
1499 | { | ||
1500 | platform_driver_unregister(&davinci_mmcsd_driver); | ||
1501 | } | ||
1502 | module_exit(davinci_mmcsd_exit); | ||
1503 | 1494 | ||
1504 | MODULE_AUTHOR("Texas Instruments India"); | 1495 | MODULE_AUTHOR("Texas Instruments India"); |
1505 | MODULE_LICENSE("GPL"); | 1496 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 72fd0f2c9013..f013e7e3746b 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c | |||
@@ -152,45 +152,8 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host) | |||
152 | return 0; | 152 | return 0; |
153 | } | 153 | } |
154 | 154 | ||
155 | static int dw_mci_exynos_setup_bus(struct dw_mci *host, | 155 | /* Common capabilities of Exynos4/Exynos5 SoC */ |
156 | struct device_node *slot_np, u8 bus_width) | 156 | static unsigned long exynos_dwmmc_caps[4] = { |
157 | { | ||
158 | int idx, gpio, ret; | ||
159 | |||
160 | if (!slot_np) | ||
161 | return -EINVAL; | ||
162 | |||
163 | /* cmd + clock + bus-width pins */ | ||
164 | for (idx = 0; idx < NUM_PINS(bus_width); idx++) { | ||
165 | gpio = of_get_gpio(slot_np, idx); | ||
166 | if (!gpio_is_valid(gpio)) { | ||
167 | dev_err(host->dev, "invalid gpio: %d\n", gpio); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | ret = devm_gpio_request(host->dev, gpio, "dw-mci-bus"); | ||
172 | if (ret) { | ||
173 | dev_err(host->dev, "gpio [%d] request failed\n", gpio); | ||
174 | return -EBUSY; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | if (host->pdata->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) | ||
179 | return 0; | ||
180 | |||
181 | gpio = of_get_named_gpio(slot_np, "samsung,cd-pinmux-gpio", 0); | ||
182 | if (gpio_is_valid(gpio)) { | ||
183 | if (devm_gpio_request(host->dev, gpio, "dw-mci-cd")) | ||
184 | dev_err(host->dev, "gpio [%d] request failed\n", gpio); | ||
185 | } else { | ||
186 | dev_info(host->dev, "cd gpio not available"); | ||
187 | } | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | /* Exynos5250 controller specific capabilities */ | ||
193 | static unsigned long exynos5250_dwmmc_caps[4] = { | ||
194 | MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | | 157 | MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | |
195 | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, | 158 | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, |
196 | MMC_CAP_CMD23, | 159 | MMC_CAP_CMD23, |
@@ -198,24 +161,25 @@ static unsigned long exynos5250_dwmmc_caps[4] = { | |||
198 | MMC_CAP_CMD23, | 161 | MMC_CAP_CMD23, |
199 | }; | 162 | }; |
200 | 163 | ||
201 | static const struct dw_mci_drv_data exynos5250_drv_data = { | 164 | static const struct dw_mci_drv_data exynos_drv_data = { |
202 | .caps = exynos5250_dwmmc_caps, | 165 | .caps = exynos_dwmmc_caps, |
203 | .init = dw_mci_exynos_priv_init, | 166 | .init = dw_mci_exynos_priv_init, |
204 | .setup_clock = dw_mci_exynos_setup_clock, | 167 | .setup_clock = dw_mci_exynos_setup_clock, |
205 | .prepare_command = dw_mci_exynos_prepare_command, | 168 | .prepare_command = dw_mci_exynos_prepare_command, |
206 | .set_ios = dw_mci_exynos_set_ios, | 169 | .set_ios = dw_mci_exynos_set_ios, |
207 | .parse_dt = dw_mci_exynos_parse_dt, | 170 | .parse_dt = dw_mci_exynos_parse_dt, |
208 | .setup_bus = dw_mci_exynos_setup_bus, | ||
209 | }; | 171 | }; |
210 | 172 | ||
211 | static const struct of_device_id dw_mci_exynos_match[] = { | 173 | static const struct of_device_id dw_mci_exynos_match[] = { |
174 | { .compatible = "samsung,exynos4412-dw-mshc", | ||
175 | .data = &exynos_drv_data, }, | ||
212 | { .compatible = "samsung,exynos5250-dw-mshc", | 176 | { .compatible = "samsung,exynos5250-dw-mshc", |
213 | .data = &exynos5250_drv_data, }, | 177 | .data = &exynos_drv_data, }, |
214 | {}, | 178 | {}, |
215 | }; | 179 | }; |
216 | MODULE_DEVICE_TABLE(of, dw_mci_exynos_match); | 180 | MODULE_DEVICE_TABLE(of, dw_mci_exynos_match); |
217 | 181 | ||
218 | int dw_mci_exynos_probe(struct platform_device *pdev) | 182 | static int dw_mci_exynos_probe(struct platform_device *pdev) |
219 | { | 183 | { |
220 | const struct dw_mci_drv_data *drv_data; | 184 | const struct dw_mci_drv_data *drv_data; |
221 | const struct of_device_id *match; | 185 | const struct of_device_id *match; |
@@ -230,7 +194,7 @@ static struct platform_driver dw_mci_exynos_pltfm_driver = { | |||
230 | .remove = __exit_p(dw_mci_pltfm_remove), | 194 | .remove = __exit_p(dw_mci_pltfm_remove), |
231 | .driver = { | 195 | .driver = { |
232 | .name = "dwmmc_exynos", | 196 | .name = "dwmmc_exynos", |
233 | .of_match_table = of_match_ptr(dw_mci_exynos_match), | 197 | .of_match_table = dw_mci_exynos_match, |
234 | .pm = &dw_mci_pltfm_pmops, | 198 | .pm = &dw_mci_pltfm_pmops, |
235 | }, | 199 | }, |
236 | }; | 200 | }; |
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 98342213ed21..bc3a1bc4940f 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -795,9 +795,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
795 | 795 | ||
796 | /* DDR mode set */ | 796 | /* DDR mode set */ |
797 | if (ios->timing == MMC_TIMING_UHS_DDR50) | 797 | if (ios->timing == MMC_TIMING_UHS_DDR50) |
798 | regs |= (0x1 << slot->id) << 16; | 798 | regs |= ((0x1 << slot->id) << 16); |
799 | else | 799 | else |
800 | regs &= ~(0x1 << slot->id) << 16; | 800 | regs &= ~((0x1 << slot->id) << 16); |
801 | 801 | ||
802 | mci_writel(slot->host, UHS_REG, regs); | 802 | mci_writel(slot->host, UHS_REG, regs); |
803 | 803 | ||
@@ -818,6 +818,20 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
818 | switch (ios->power_mode) { | 818 | switch (ios->power_mode) { |
819 | case MMC_POWER_UP: | 819 | case MMC_POWER_UP: |
820 | set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); | 820 | set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); |
821 | /* Power up slot */ | ||
822 | if (slot->host->pdata->setpower) | ||
823 | slot->host->pdata->setpower(slot->id, mmc->ocr_avail); | ||
824 | regs = mci_readl(slot->host, PWREN); | ||
825 | regs |= (1 << slot->id); | ||
826 | mci_writel(slot->host, PWREN, regs); | ||
827 | break; | ||
828 | case MMC_POWER_OFF: | ||
829 | /* Power down slot */ | ||
830 | if (slot->host->pdata->setpower) | ||
831 | slot->host->pdata->setpower(slot->id, 0); | ||
832 | regs = mci_readl(slot->host, PWREN); | ||
833 | regs &= ~(1 << slot->id); | ||
834 | mci_writel(slot->host, PWREN, regs); | ||
821 | break; | 835 | break; |
822 | default: | 836 | default: |
823 | break; | 837 | break; |
@@ -1191,12 +1205,15 @@ static void dw_mci_pull_final_bytes(struct dw_mci *host, void *buf, int cnt) | |||
1191 | 1205 | ||
1192 | static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) | 1206 | static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) |
1193 | { | 1207 | { |
1208 | struct mmc_data *data = host->data; | ||
1209 | int init_cnt = cnt; | ||
1210 | |||
1194 | /* try and push anything in the part_buf */ | 1211 | /* try and push anything in the part_buf */ |
1195 | if (unlikely(host->part_buf_count)) { | 1212 | if (unlikely(host->part_buf_count)) { |
1196 | int len = dw_mci_push_part_bytes(host, buf, cnt); | 1213 | int len = dw_mci_push_part_bytes(host, buf, cnt); |
1197 | buf += len; | 1214 | buf += len; |
1198 | cnt -= len; | 1215 | cnt -= len; |
1199 | if (!sg_next(host->sg) || host->part_buf_count == 2) { | 1216 | if (host->part_buf_count == 2) { |
1200 | mci_writew(host, DATA(host->data_offset), | 1217 | mci_writew(host, DATA(host->data_offset), |
1201 | host->part_buf16); | 1218 | host->part_buf16); |
1202 | host->part_buf_count = 0; | 1219 | host->part_buf_count = 0; |
@@ -1229,9 +1246,11 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) | |||
1229 | /* put anything remaining in the part_buf */ | 1246 | /* put anything remaining in the part_buf */ |
1230 | if (cnt) { | 1247 | if (cnt) { |
1231 | dw_mci_set_part_bytes(host, buf, cnt); | 1248 | dw_mci_set_part_bytes(host, buf, cnt); |
1232 | if (!sg_next(host->sg)) | 1249 | /* Push data if we have reached the expected data length */ |
1250 | if ((data->bytes_xfered + init_cnt) == | ||
1251 | (data->blksz * data->blocks)) | ||
1233 | mci_writew(host, DATA(host->data_offset), | 1252 | mci_writew(host, DATA(host->data_offset), |
1234 | host->part_buf16); | 1253 | host->part_buf16); |
1235 | } | 1254 | } |
1236 | } | 1255 | } |
1237 | 1256 | ||
@@ -1269,12 +1288,15 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt) | |||
1269 | 1288 | ||
1270 | static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) | 1289 | static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) |
1271 | { | 1290 | { |
1291 | struct mmc_data *data = host->data; | ||
1292 | int init_cnt = cnt; | ||
1293 | |||
1272 | /* try and push anything in the part_buf */ | 1294 | /* try and push anything in the part_buf */ |
1273 | if (unlikely(host->part_buf_count)) { | 1295 | if (unlikely(host->part_buf_count)) { |
1274 | int len = dw_mci_push_part_bytes(host, buf, cnt); | 1296 | int len = dw_mci_push_part_bytes(host, buf, cnt); |
1275 | buf += len; | 1297 | buf += len; |
1276 | cnt -= len; | 1298 | cnt -= len; |
1277 | if (!sg_next(host->sg) || host->part_buf_count == 4) { | 1299 | if (host->part_buf_count == 4) { |
1278 | mci_writel(host, DATA(host->data_offset), | 1300 | mci_writel(host, DATA(host->data_offset), |
1279 | host->part_buf32); | 1301 | host->part_buf32); |
1280 | host->part_buf_count = 0; | 1302 | host->part_buf_count = 0; |
@@ -1307,9 +1329,11 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) | |||
1307 | /* put anything remaining in the part_buf */ | 1329 | /* put anything remaining in the part_buf */ |
1308 | if (cnt) { | 1330 | if (cnt) { |
1309 | dw_mci_set_part_bytes(host, buf, cnt); | 1331 | dw_mci_set_part_bytes(host, buf, cnt); |
1310 | if (!sg_next(host->sg)) | 1332 | /* Push data if we have reached the expected data length */ |
1333 | if ((data->bytes_xfered + init_cnt) == | ||
1334 | (data->blksz * data->blocks)) | ||
1311 | mci_writel(host, DATA(host->data_offset), | 1335 | mci_writel(host, DATA(host->data_offset), |
1312 | host->part_buf32); | 1336 | host->part_buf32); |
1313 | } | 1337 | } |
1314 | } | 1338 | } |
1315 | 1339 | ||
@@ -1347,13 +1371,17 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt) | |||
1347 | 1371 | ||
1348 | static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) | 1372 | static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) |
1349 | { | 1373 | { |
1374 | struct mmc_data *data = host->data; | ||
1375 | int init_cnt = cnt; | ||
1376 | |||
1350 | /* try and push anything in the part_buf */ | 1377 | /* try and push anything in the part_buf */ |
1351 | if (unlikely(host->part_buf_count)) { | 1378 | if (unlikely(host->part_buf_count)) { |
1352 | int len = dw_mci_push_part_bytes(host, buf, cnt); | 1379 | int len = dw_mci_push_part_bytes(host, buf, cnt); |
1353 | buf += len; | 1380 | buf += len; |
1354 | cnt -= len; | 1381 | cnt -= len; |
1355 | if (!sg_next(host->sg) || host->part_buf_count == 8) { | 1382 | |
1356 | mci_writew(host, DATA(host->data_offset), | 1383 | if (host->part_buf_count == 8) { |
1384 | mci_writeq(host, DATA(host->data_offset), | ||
1357 | host->part_buf); | 1385 | host->part_buf); |
1358 | host->part_buf_count = 0; | 1386 | host->part_buf_count = 0; |
1359 | } | 1387 | } |
@@ -1385,9 +1413,11 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) | |||
1385 | /* put anything remaining in the part_buf */ | 1413 | /* put anything remaining in the part_buf */ |
1386 | if (cnt) { | 1414 | if (cnt) { |
1387 | dw_mci_set_part_bytes(host, buf, cnt); | 1415 | dw_mci_set_part_bytes(host, buf, cnt); |
1388 | if (!sg_next(host->sg)) | 1416 | /* Push data if we have reached the expected data length */ |
1417 | if ((data->bytes_xfered + init_cnt) == | ||
1418 | (data->blksz * data->blocks)) | ||
1389 | mci_writeq(host, DATA(host->data_offset), | 1419 | mci_writeq(host, DATA(host->data_offset), |
1390 | host->part_buf); | 1420 | host->part_buf); |
1391 | } | 1421 | } |
1392 | } | 1422 | } |
1393 | 1423 | ||
@@ -1438,7 +1468,7 @@ static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt) | |||
1438 | host->pull_data(host, buf, cnt); | 1468 | host->pull_data(host, buf, cnt); |
1439 | } | 1469 | } |
1440 | 1470 | ||
1441 | static void dw_mci_read_data_pio(struct dw_mci *host) | 1471 | static void dw_mci_read_data_pio(struct dw_mci *host, bool dto) |
1442 | { | 1472 | { |
1443 | struct sg_mapping_iter *sg_miter = &host->sg_miter; | 1473 | struct sg_mapping_iter *sg_miter = &host->sg_miter; |
1444 | void *buf; | 1474 | void *buf; |
@@ -1446,7 +1476,7 @@ static void dw_mci_read_data_pio(struct dw_mci *host) | |||
1446 | struct mmc_data *data = host->data; | 1476 | struct mmc_data *data = host->data; |
1447 | int shift = host->data_shift; | 1477 | int shift = host->data_shift; |
1448 | u32 status; | 1478 | u32 status; |
1449 | unsigned int nbytes = 0, len; | 1479 | unsigned int len; |
1450 | unsigned int remain, fcnt; | 1480 | unsigned int remain, fcnt; |
1451 | 1481 | ||
1452 | do { | 1482 | do { |
@@ -1465,16 +1495,17 @@ static void dw_mci_read_data_pio(struct dw_mci *host) | |||
1465 | if (!len) | 1495 | if (!len) |
1466 | break; | 1496 | break; |
1467 | dw_mci_pull_data(host, (void *)(buf + offset), len); | 1497 | dw_mci_pull_data(host, (void *)(buf + offset), len); |
1498 | data->bytes_xfered += len; | ||
1468 | offset += len; | 1499 | offset += len; |
1469 | nbytes += len; | ||
1470 | remain -= len; | 1500 | remain -= len; |
1471 | } while (remain); | 1501 | } while (remain); |
1472 | 1502 | ||
1473 | sg_miter->consumed = offset; | 1503 | sg_miter->consumed = offset; |
1474 | status = mci_readl(host, MINTSTS); | 1504 | status = mci_readl(host, MINTSTS); |
1475 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); | 1505 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); |
1476 | } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ | 1506 | /* if the RXDR is ready read again */ |
1477 | data->bytes_xfered += nbytes; | 1507 | } while ((status & SDMMC_INT_RXDR) || |
1508 | (dto && SDMMC_GET_FCNT(mci_readl(host, STATUS)))); | ||
1478 | 1509 | ||
1479 | if (!remain) { | 1510 | if (!remain) { |
1480 | if (!sg_miter_next(sg_miter)) | 1511 | if (!sg_miter_next(sg_miter)) |
@@ -1485,7 +1516,6 @@ static void dw_mci_read_data_pio(struct dw_mci *host) | |||
1485 | return; | 1516 | return; |
1486 | 1517 | ||
1487 | done: | 1518 | done: |
1488 | data->bytes_xfered += nbytes; | ||
1489 | sg_miter_stop(sg_miter); | 1519 | sg_miter_stop(sg_miter); |
1490 | host->sg = NULL; | 1520 | host->sg = NULL; |
1491 | smp_wmb(); | 1521 | smp_wmb(); |
@@ -1500,7 +1530,7 @@ static void dw_mci_write_data_pio(struct dw_mci *host) | |||
1500 | struct mmc_data *data = host->data; | 1530 | struct mmc_data *data = host->data; |
1501 | int shift = host->data_shift; | 1531 | int shift = host->data_shift; |
1502 | u32 status; | 1532 | u32 status; |
1503 | unsigned int nbytes = 0, len; | 1533 | unsigned int len; |
1504 | unsigned int fifo_depth = host->fifo_depth; | 1534 | unsigned int fifo_depth = host->fifo_depth; |
1505 | unsigned int remain, fcnt; | 1535 | unsigned int remain, fcnt; |
1506 | 1536 | ||
@@ -1521,8 +1551,8 @@ static void dw_mci_write_data_pio(struct dw_mci *host) | |||
1521 | if (!len) | 1551 | if (!len) |
1522 | break; | 1552 | break; |
1523 | host->push_data(host, (void *)(buf + offset), len); | 1553 | host->push_data(host, (void *)(buf + offset), len); |
1554 | data->bytes_xfered += len; | ||
1524 | offset += len; | 1555 | offset += len; |
1525 | nbytes += len; | ||
1526 | remain -= len; | 1556 | remain -= len; |
1527 | } while (remain); | 1557 | } while (remain); |
1528 | 1558 | ||
@@ -1530,7 +1560,6 @@ static void dw_mci_write_data_pio(struct dw_mci *host) | |||
1530 | status = mci_readl(host, MINTSTS); | 1560 | status = mci_readl(host, MINTSTS); |
1531 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); | 1561 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); |
1532 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ | 1562 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ |
1533 | data->bytes_xfered += nbytes; | ||
1534 | 1563 | ||
1535 | if (!remain) { | 1564 | if (!remain) { |
1536 | if (!sg_miter_next(sg_miter)) | 1565 | if (!sg_miter_next(sg_miter)) |
@@ -1541,7 +1570,6 @@ static void dw_mci_write_data_pio(struct dw_mci *host) | |||
1541 | return; | 1570 | return; |
1542 | 1571 | ||
1543 | done: | 1572 | done: |
1544 | data->bytes_xfered += nbytes; | ||
1545 | sg_miter_stop(sg_miter); | 1573 | sg_miter_stop(sg_miter); |
1546 | host->sg = NULL; | 1574 | host->sg = NULL; |
1547 | smp_wmb(); | 1575 | smp_wmb(); |
@@ -1563,11 +1591,11 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | |||
1563 | { | 1591 | { |
1564 | struct dw_mci *host = dev_id; | 1592 | struct dw_mci *host = dev_id; |
1565 | u32 pending; | 1593 | u32 pending; |
1566 | unsigned int pass_count = 0; | ||
1567 | int i; | 1594 | int i; |
1568 | 1595 | ||
1569 | do { | 1596 | pending = mci_readl(host, MINTSTS); /* read-only mask reg */ |
1570 | pending = mci_readl(host, MINTSTS); /* read-only mask reg */ | 1597 | |
1598 | if (pending) { | ||
1571 | 1599 | ||
1572 | /* | 1600 | /* |
1573 | * DTO fix - version 2.10a and below, and only if internal DMA | 1601 | * DTO fix - version 2.10a and below, and only if internal DMA |
@@ -1579,9 +1607,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | |||
1579 | pending |= SDMMC_INT_DATA_OVER; | 1607 | pending |= SDMMC_INT_DATA_OVER; |
1580 | } | 1608 | } |
1581 | 1609 | ||
1582 | if (!pending) | ||
1583 | break; | ||
1584 | |||
1585 | if (pending & DW_MCI_CMD_ERROR_FLAGS) { | 1610 | if (pending & DW_MCI_CMD_ERROR_FLAGS) { |
1586 | mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); | 1611 | mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); |
1587 | host->cmd_status = pending; | 1612 | host->cmd_status = pending; |
@@ -1605,7 +1630,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | |||
1605 | smp_wmb(); | 1630 | smp_wmb(); |
1606 | if (host->dir_status == DW_MCI_RECV_STATUS) { | 1631 | if (host->dir_status == DW_MCI_RECV_STATUS) { |
1607 | if (host->sg != NULL) | 1632 | if (host->sg != NULL) |
1608 | dw_mci_read_data_pio(host); | 1633 | dw_mci_read_data_pio(host, true); |
1609 | } | 1634 | } |
1610 | set_bit(EVENT_DATA_COMPLETE, &host->pending_events); | 1635 | set_bit(EVENT_DATA_COMPLETE, &host->pending_events); |
1611 | tasklet_schedule(&host->tasklet); | 1636 | tasklet_schedule(&host->tasklet); |
@@ -1614,7 +1639,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | |||
1614 | if (pending & SDMMC_INT_RXDR) { | 1639 | if (pending & SDMMC_INT_RXDR) { |
1615 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); | 1640 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); |
1616 | if (host->dir_status == DW_MCI_RECV_STATUS && host->sg) | 1641 | if (host->dir_status == DW_MCI_RECV_STATUS && host->sg) |
1617 | dw_mci_read_data_pio(host); | 1642 | dw_mci_read_data_pio(host, false); |
1618 | } | 1643 | } |
1619 | 1644 | ||
1620 | if (pending & SDMMC_INT_TXDR) { | 1645 | if (pending & SDMMC_INT_TXDR) { |
@@ -1642,7 +1667,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | |||
1642 | } | 1667 | } |
1643 | } | 1668 | } |
1644 | 1669 | ||
1645 | } while (pass_count++ < 5); | 1670 | } |
1646 | 1671 | ||
1647 | #ifdef CONFIG_MMC_DW_IDMAC | 1672 | #ifdef CONFIG_MMC_DW_IDMAC |
1648 | /* Handle DMA interrupts */ | 1673 | /* Handle DMA interrupts */ |
@@ -1674,10 +1699,6 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
1674 | dev_dbg(&slot->mmc->class_dev, "card %s\n", | 1699 | dev_dbg(&slot->mmc->class_dev, "card %s\n", |
1675 | present ? "inserted" : "removed"); | 1700 | present ? "inserted" : "removed"); |
1676 | 1701 | ||
1677 | /* Power up slot (before spin_lock, may sleep) */ | ||
1678 | if (present != 0 && host->pdata->setpower) | ||
1679 | host->pdata->setpower(slot->id, mmc->ocr_avail); | ||
1680 | |||
1681 | spin_lock_bh(&host->lock); | 1702 | spin_lock_bh(&host->lock); |
1682 | 1703 | ||
1683 | /* Card change detected */ | 1704 | /* Card change detected */ |
@@ -1760,10 +1781,6 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
1760 | 1781 | ||
1761 | spin_unlock_bh(&host->lock); | 1782 | spin_unlock_bh(&host->lock); |
1762 | 1783 | ||
1763 | /* Power down slot (after spin_unlock, may sleep) */ | ||
1764 | if (present == 0 && host->pdata->setpower) | ||
1765 | host->pdata->setpower(slot->id, 0); | ||
1766 | |||
1767 | present = dw_mci_get_cd(mmc); | 1784 | present = dw_mci_get_cd(mmc); |
1768 | } | 1785 | } |
1769 | 1786 | ||
@@ -1935,14 +1952,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1935 | else | 1952 | else |
1936 | bus_width = 1; | 1953 | bus_width = 1; |
1937 | 1954 | ||
1938 | if (drv_data && drv_data->setup_bus) { | ||
1939 | struct device_node *slot_np; | ||
1940 | slot_np = dw_mci_of_find_slot_node(host->dev, slot->id); | ||
1941 | ret = drv_data->setup_bus(host, slot_np, bus_width); | ||
1942 | if (ret) | ||
1943 | goto err_setup_bus; | ||
1944 | } | ||
1945 | |||
1946 | switch (bus_width) { | 1955 | switch (bus_width) { |
1947 | case 8: | 1956 | case 8: |
1948 | mmc->caps |= MMC_CAP_8_BIT_DATA; | 1957 | mmc->caps |= MMC_CAP_8_BIT_DATA; |
@@ -1980,8 +1989,14 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1980 | if (IS_ERR(host->vmmc)) { | 1989 | if (IS_ERR(host->vmmc)) { |
1981 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); | 1990 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); |
1982 | host->vmmc = NULL; | 1991 | host->vmmc = NULL; |
1983 | } else | 1992 | } else { |
1984 | regulator_enable(host->vmmc); | 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 | } | ||
1985 | 2000 | ||
1986 | if (dw_mci_get_cd(mmc)) | 2001 | if (dw_mci_get_cd(mmc)) |
1987 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); | 2002 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); |
@@ -1990,7 +2005,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1990 | 2005 | ||
1991 | slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id); | 2006 | slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id); |
1992 | 2007 | ||
1993 | mmc_add_host(mmc); | 2008 | ret = mmc_add_host(mmc); |
2009 | if (ret) | ||
2010 | goto err_setup_bus; | ||
1994 | 2011 | ||
1995 | #if defined(CONFIG_DEBUG_FS) | 2012 | #if defined(CONFIG_DEBUG_FS) |
1996 | dw_mci_init_debugfs(slot); | 2013 | dw_mci_init_debugfs(slot); |
@@ -2289,6 +2306,18 @@ int dw_mci_probe(struct dw_mci *host) | |||
2289 | mci_writel(host, CLKENA, 0); | 2306 | mci_writel(host, CLKENA, 0); |
2290 | mci_writel(host, CLKSRC, 0); | 2307 | mci_writel(host, CLKSRC, 0); |
2291 | 2308 | ||
2309 | /* | ||
2310 | * In 2.40a spec, Data offset is changed. | ||
2311 | * Need to check the version-id and set data-offset for DATA register. | ||
2312 | */ | ||
2313 | host->verid = SDMMC_GET_VERID(mci_readl(host, VERID)); | ||
2314 | dev_info(host->dev, "Version ID is %04x\n", host->verid); | ||
2315 | |||
2316 | if (host->verid < DW_MMC_240A) | ||
2317 | host->data_offset = DATA_OFFSET; | ||
2318 | else | ||
2319 | host->data_offset = DATA_240A_OFFSET; | ||
2320 | |||
2292 | tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); | 2321 | tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); |
2293 | host->card_workqueue = alloc_workqueue("dw-mci-card", | 2322 | host->card_workqueue = alloc_workqueue("dw-mci-card", |
2294 | WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1); | 2323 | WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1); |
@@ -2337,18 +2366,6 @@ int dw_mci_probe(struct dw_mci *host) | |||
2337 | goto err_workqueue; | 2366 | goto err_workqueue; |
2338 | } | 2367 | } |
2339 | 2368 | ||
2340 | /* | ||
2341 | * In 2.40a spec, Data offset is changed. | ||
2342 | * Need to check the version-id and set data-offset for DATA register. | ||
2343 | */ | ||
2344 | host->verid = SDMMC_GET_VERID(mci_readl(host, VERID)); | ||
2345 | dev_info(host->dev, "Version ID is %04x\n", host->verid); | ||
2346 | |||
2347 | if (host->verid < DW_MMC_240A) | ||
2348 | host->data_offset = DATA_OFFSET; | ||
2349 | else | ||
2350 | host->data_offset = DATA_240A_OFFSET; | ||
2351 | |||
2352 | if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) | 2369 | if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) |
2353 | dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); | 2370 | dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); |
2354 | 2371 | ||
@@ -2445,8 +2462,14 @@ int dw_mci_resume(struct dw_mci *host) | |||
2445 | { | 2462 | { |
2446 | int i, ret; | 2463 | int i, ret; |
2447 | 2464 | ||
2448 | if (host->vmmc) | 2465 | if (host->vmmc) { |
2449 | regulator_enable(host->vmmc); | 2466 | ret = regulator_enable(host->vmmc); |
2467 | if (ret) { | ||
2468 | dev_err(host->dev, | ||
2469 | "failed to enable regulator: %d\n", ret); | ||
2470 | return ret; | ||
2471 | } | ||
2472 | } | ||
2450 | 2473 | ||
2451 | if (!mci_wait_reset(host->dev, host)) { | 2474 | if (!mci_wait_reset(host->dev, host)) { |
2452 | ret = -ENODEV; | 2475 | ret = -ENODEV; |
@@ -2485,7 +2508,7 @@ EXPORT_SYMBOL(dw_mci_resume); | |||
2485 | 2508 | ||
2486 | static int __init dw_mci_init(void) | 2509 | static int __init dw_mci_init(void) |
2487 | { | 2510 | { |
2488 | printk(KERN_INFO "Synopsys Designware Multimedia Card Interface Driver"); | 2511 | pr_info("Synopsys Designware Multimedia Card Interface Driver\n"); |
2489 | return 0; | 2512 | return 0; |
2490 | } | 2513 | } |
2491 | 2514 | ||
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 53b8fd987e47..0b74189e7ee7 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h | |||
@@ -190,7 +190,6 @@ extern int dw_mci_resume(struct dw_mci *host); | |||
190 | * @prepare_command: handle CMD register extensions. | 190 | * @prepare_command: handle CMD register extensions. |
191 | * @set_ios: handle bus specific extensions. | 191 | * @set_ios: handle bus specific extensions. |
192 | * @parse_dt: parse implementation specific device tree properties. | 192 | * @parse_dt: parse implementation specific device tree properties. |
193 | * @setup_bus: initialize io-interface | ||
194 | * | 193 | * |
195 | * Provide controller implementation specific extensions. The usage of this | 194 | * Provide controller implementation specific extensions. The usage of this |
196 | * data structure is fully optional and usage of each member in this structure | 195 | * data structure is fully optional and usage of each member in this structure |
@@ -203,7 +202,5 @@ struct dw_mci_drv_data { | |||
203 | void (*prepare_command)(struct dw_mci *host, u32 *cmdr); | 202 | void (*prepare_command)(struct dw_mci *host, u32 *cmdr); |
204 | void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); | 203 | void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); |
205 | int (*parse_dt)(struct dw_mci *host); | 204 | int (*parse_dt)(struct dw_mci *host); |
206 | int (*setup_bus)(struct dw_mci *host, | ||
207 | struct device_node *slot_np, u8 bus_width); | ||
208 | }; | 205 | }; |
209 | #endif /* _DW_MMC_H_ */ | 206 | #endif /* _DW_MMC_H_ */ |
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 145cdaf000d1..8960fc846c77 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
@@ -119,10 +119,8 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data) | |||
119 | host->pio_size = data->blocks * data->blksz; | 119 | host->pio_size = data->blocks * data->blksz; |
120 | host->pio_ptr = sg_virt(data->sg); | 120 | host->pio_ptr = sg_virt(data->sg); |
121 | if (!nodma) | 121 | if (!nodma) |
122 | pr_debug("%s: fallback to PIO for data " | 122 | dev_dbg(host->dev, "fallback to PIO for data at 0x%p size %d\n", |
123 | "at 0x%p size %d\n", | 123 | host->pio_ptr, host->pio_size); |
124 | mmc_hostname(host->mmc), | ||
125 | host->pio_ptr, host->pio_size); | ||
126 | return 1; | 124 | return 1; |
127 | } else { | 125 | } else { |
128 | dma_addr_t phys_addr; | 126 | dma_addr_t phys_addr; |
@@ -473,8 +471,8 @@ static irqreturn_t mvsd_irq(int irq, void *dev) | |||
473 | if (mrq->data) | 471 | if (mrq->data) |
474 | err_status = mvsd_finish_data(host, mrq->data, err_status); | 472 | err_status = mvsd_finish_data(host, mrq->data, err_status); |
475 | if (err_status) { | 473 | if (err_status) { |
476 | pr_err("%s: unhandled error status %#04x\n", | 474 | dev_err(host->dev, "unhandled error status %#04x\n", |
477 | mmc_hostname(host->mmc), err_status); | 475 | err_status); |
478 | cmd->error = -ENOMSG; | 476 | cmd->error = -ENOMSG; |
479 | } | 477 | } |
480 | 478 | ||
@@ -491,9 +489,8 @@ static irqreturn_t mvsd_irq(int irq, void *dev) | |||
491 | if (irq_handled) | 489 | if (irq_handled) |
492 | return IRQ_HANDLED; | 490 | return IRQ_HANDLED; |
493 | 491 | ||
494 | pr_err("%s: unhandled interrupt status=0x%04x en=0x%04x " | 492 | dev_err(host->dev, "unhandled interrupt status=0x%04x en=0x%04x pio=%d\n", |
495 | "pio=%d\n", mmc_hostname(host->mmc), intr_status, | 493 | intr_status, host->intr_en, host->pio_size); |
496 | host->intr_en, host->pio_size); | ||
497 | return IRQ_NONE; | 494 | return IRQ_NONE; |
498 | } | 495 | } |
499 | 496 | ||
@@ -507,13 +504,11 @@ static void mvsd_timeout_timer(unsigned long data) | |||
507 | spin_lock_irqsave(&host->lock, flags); | 504 | spin_lock_irqsave(&host->lock, flags); |
508 | mrq = host->mrq; | 505 | mrq = host->mrq; |
509 | if (mrq) { | 506 | if (mrq) { |
510 | pr_err("%s: Timeout waiting for hardware interrupt.\n", | 507 | dev_err(host->dev, "Timeout waiting for hardware interrupt.\n"); |
511 | mmc_hostname(host->mmc)); | 508 | dev_err(host->dev, "hw_state=0x%04x, intr_status=0x%04x intr_en=0x%04x\n", |
512 | pr_err("%s: hw_state=0x%04x, intr_status=0x%04x " | 509 | mvsd_read(MVSD_HW_STATE), |
513 | "intr_en=0x%04x\n", mmc_hostname(host->mmc), | 510 | mvsd_read(MVSD_NOR_INTR_STATUS), |
514 | mvsd_read(MVSD_HW_STATE), | 511 | mvsd_read(MVSD_NOR_INTR_EN)); |
515 | mvsd_read(MVSD_NOR_INTR_STATUS), | ||
516 | mvsd_read(MVSD_NOR_INTR_EN)); | ||
517 | 512 | ||
518 | host->mrq = NULL; | 513 | host->mrq = NULL; |
519 | 514 | ||
@@ -741,8 +736,8 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
741 | goto out; | 736 | goto out; |
742 | } | 737 | } |
743 | host->base_clock = mvsd_data->clock / 2; | 738 | host->base_clock = mvsd_data->clock / 2; |
744 | gpio_card_detect = mvsd_data->gpio_card_detect; | 739 | gpio_card_detect = mvsd_data->gpio_card_detect ? : -EINVAL; |
745 | gpio_write_protect = mvsd_data->gpio_write_protect; | 740 | gpio_write_protect = mvsd_data->gpio_write_protect ? : -EINVAL; |
746 | } | 741 | } |
747 | 742 | ||
748 | mmc->ops = &mvsd_ops; | 743 | mmc->ops = &mvsd_ops; |
@@ -778,7 +773,7 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
778 | 773 | ||
779 | ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host); | 774 | ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host); |
780 | if (ret) { | 775 | if (ret) { |
781 | pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq); | 776 | dev_err(&pdev->dev, "cannot assign irq %d\n", irq); |
782 | goto out; | 777 | goto out; |
783 | } | 778 | } |
784 | 779 | ||
@@ -797,13 +792,11 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
797 | if (ret) | 792 | if (ret) |
798 | goto out; | 793 | goto out; |
799 | 794 | ||
800 | pr_notice("%s: %s driver initialized, ", | ||
801 | mmc_hostname(mmc), DRIVER_NAME); | ||
802 | if (!(mmc->caps & MMC_CAP_NEEDS_POLL)) | 795 | if (!(mmc->caps & MMC_CAP_NEEDS_POLL)) |
803 | printk("using GPIO %d for card detection\n", | 796 | dev_notice(&pdev->dev, "using GPIO %d for card detection\n", |
804 | gpio_card_detect); | 797 | gpio_card_detect); |
805 | else | 798 | else |
806 | printk("lacking card detect (fall back to polling)\n"); | 799 | dev_notice(&pdev->dev, "lacking card detect (fall back to polling)\n"); |
807 | return 0; | 800 | return 0; |
808 | 801 | ||
809 | out: | 802 | out: |
@@ -881,18 +874,7 @@ static struct platform_driver mvsd_driver = { | |||
881 | }, | 874 | }, |
882 | }; | 875 | }; |
883 | 876 | ||
884 | static int __init mvsd_init(void) | 877 | module_platform_driver_probe(mvsd_driver, mvsd_probe); |
885 | { | ||
886 | return platform_driver_probe(&mvsd_driver, mvsd_probe); | ||
887 | } | ||
888 | |||
889 | static void __exit mvsd_exit(void) | ||
890 | { | ||
891 | platform_driver_unregister(&mvsd_driver); | ||
892 | } | ||
893 | |||
894 | module_init(mvsd_init); | ||
895 | module_exit(mvsd_exit); | ||
896 | 878 | ||
897 | /* maximum card clock frequency (default 50MHz) */ | 879 | /* maximum card clock frequency (default 50MHz) */ |
898 | module_param(maxfreq, int, 0); | 880 | module_param(maxfreq, int, 0); |
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index a72936eea6fa..d5036353bddc 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -34,10 +34,14 @@ | |||
34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
35 | #include <linux/dmaengine.h> | 35 | #include <linux/dmaengine.h> |
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/of.h> | ||
38 | #include <linux/of_device.h> | ||
39 | #include <linux/of_dma.h> | ||
40 | #include <linux/of_gpio.h> | ||
41 | #include <linux/mmc/slot-gpio.h> | ||
37 | 42 | ||
38 | #include <asm/dma.h> | 43 | #include <asm/dma.h> |
39 | #include <asm/irq.h> | 44 | #include <asm/irq.h> |
40 | #include <asm/sizes.h> | ||
41 | #include <linux/platform_data/mmc-mxcmmc.h> | 45 | #include <linux/platform_data/mmc-mxcmmc.h> |
42 | 46 | ||
43 | #include <linux/platform_data/dma-imx.h> | 47 | #include <linux/platform_data/dma-imx.h> |
@@ -115,6 +119,7 @@ | |||
115 | enum mxcmci_type { | 119 | enum mxcmci_type { |
116 | IMX21_MMC, | 120 | IMX21_MMC, |
117 | IMX31_MMC, | 121 | IMX31_MMC, |
122 | MPC512X_MMC, | ||
118 | }; | 123 | }; |
119 | 124 | ||
120 | struct mxcmci_host { | 125 | struct mxcmci_host { |
@@ -160,7 +165,7 @@ struct mxcmci_host { | |||
160 | enum mxcmci_type devtype; | 165 | enum mxcmci_type devtype; |
161 | }; | 166 | }; |
162 | 167 | ||
163 | static struct platform_device_id mxcmci_devtype[] = { | 168 | static const struct platform_device_id mxcmci_devtype[] = { |
164 | { | 169 | { |
165 | .name = "imx21-mmc", | 170 | .name = "imx21-mmc", |
166 | .driver_data = IMX21_MMC, | 171 | .driver_data = IMX21_MMC, |
@@ -168,16 +173,72 @@ static struct platform_device_id mxcmci_devtype[] = { | |||
168 | .name = "imx31-mmc", | 173 | .name = "imx31-mmc", |
169 | .driver_data = IMX31_MMC, | 174 | .driver_data = IMX31_MMC, |
170 | }, { | 175 | }, { |
176 | .name = "mpc512x-sdhc", | ||
177 | .driver_data = MPC512X_MMC, | ||
178 | }, { | ||
171 | /* sentinel */ | 179 | /* sentinel */ |
172 | } | 180 | } |
173 | }; | 181 | }; |
174 | MODULE_DEVICE_TABLE(platform, mxcmci_devtype); | 182 | MODULE_DEVICE_TABLE(platform, mxcmci_devtype); |
175 | 183 | ||
184 | static const struct of_device_id mxcmci_of_match[] = { | ||
185 | { | ||
186 | .compatible = "fsl,imx21-mmc", | ||
187 | .data = &mxcmci_devtype[IMX21_MMC], | ||
188 | }, { | ||
189 | .compatible = "fsl,imx31-mmc", | ||
190 | .data = &mxcmci_devtype[IMX31_MMC], | ||
191 | }, { | ||
192 | .compatible = "fsl,mpc5121-sdhc", | ||
193 | .data = &mxcmci_devtype[MPC512X_MMC], | ||
194 | }, { | ||
195 | /* sentinel */ | ||
196 | } | ||
197 | }; | ||
198 | MODULE_DEVICE_TABLE(of, mxcmci_of_match); | ||
199 | |||
176 | static inline int is_imx31_mmc(struct mxcmci_host *host) | 200 | static inline int is_imx31_mmc(struct mxcmci_host *host) |
177 | { | 201 | { |
178 | return host->devtype == IMX31_MMC; | 202 | return host->devtype == IMX31_MMC; |
179 | } | 203 | } |
180 | 204 | ||
205 | static inline int is_mpc512x_mmc(struct mxcmci_host *host) | ||
206 | { | ||
207 | return host->devtype == MPC512X_MMC; | ||
208 | } | ||
209 | |||
210 | static inline u32 mxcmci_readl(struct mxcmci_host *host, int reg) | ||
211 | { | ||
212 | if (IS_ENABLED(CONFIG_PPC_MPC512x)) | ||
213 | return ioread32be(host->base + reg); | ||
214 | else | ||
215 | return readl(host->base + reg); | ||
216 | } | ||
217 | |||
218 | static inline void mxcmci_writel(struct mxcmci_host *host, u32 val, int reg) | ||
219 | { | ||
220 | if (IS_ENABLED(CONFIG_PPC_MPC512x)) | ||
221 | iowrite32be(val, host->base + reg); | ||
222 | else | ||
223 | writel(val, host->base + reg); | ||
224 | } | ||
225 | |||
226 | static inline u16 mxcmci_readw(struct mxcmci_host *host, int reg) | ||
227 | { | ||
228 | if (IS_ENABLED(CONFIG_PPC_MPC512x)) | ||
229 | return ioread32be(host->base + reg); | ||
230 | else | ||
231 | return readw(host->base + reg); | ||
232 | } | ||
233 | |||
234 | static inline void mxcmci_writew(struct mxcmci_host *host, u16 val, int reg) | ||
235 | { | ||
236 | if (IS_ENABLED(CONFIG_PPC_MPC512x)) | ||
237 | iowrite32be(val, host->base + reg); | ||
238 | else | ||
239 | writew(val, host->base + reg); | ||
240 | } | ||
241 | |||
181 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); | 242 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); |
182 | 243 | ||
183 | static inline void mxcmci_init_ocr(struct mxcmci_host *host) | 244 | static inline void mxcmci_init_ocr(struct mxcmci_host *host) |
@@ -229,17 +290,40 @@ static void mxcmci_softreset(struct mxcmci_host *host) | |||
229 | dev_dbg(mmc_dev(host->mmc), "mxcmci_softreset\n"); | 290 | dev_dbg(mmc_dev(host->mmc), "mxcmci_softreset\n"); |
230 | 291 | ||
231 | /* reset sequence */ | 292 | /* reset sequence */ |
232 | writew(STR_STP_CLK_RESET, host->base + MMC_REG_STR_STP_CLK); | 293 | mxcmci_writew(host, STR_STP_CLK_RESET, MMC_REG_STR_STP_CLK); |
233 | writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK, | 294 | mxcmci_writew(host, STR_STP_CLK_RESET | STR_STP_CLK_START_CLK, |
234 | host->base + MMC_REG_STR_STP_CLK); | 295 | MMC_REG_STR_STP_CLK); |
235 | 296 | ||
236 | for (i = 0; i < 8; i++) | 297 | for (i = 0; i < 8; i++) |
237 | writew(STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK); | 298 | mxcmci_writew(host, STR_STP_CLK_START_CLK, MMC_REG_STR_STP_CLK); |
238 | 299 | ||
239 | writew(0xff, host->base + MMC_REG_RES_TO); | 300 | mxcmci_writew(host, 0xff, MMC_REG_RES_TO); |
240 | } | 301 | } |
241 | static int mxcmci_setup_dma(struct mmc_host *mmc); | 302 | static int mxcmci_setup_dma(struct mmc_host *mmc); |
242 | 303 | ||
304 | #if IS_ENABLED(CONFIG_PPC_MPC512x) | ||
305 | static inline void buffer_swap32(u32 *buf, int len) | ||
306 | { | ||
307 | int i; | ||
308 | |||
309 | for (i = 0; i < ((len + 3) / 4); i++) { | ||
310 | st_le32(buf, *buf); | ||
311 | buf++; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | static void mxcmci_swap_buffers(struct mmc_data *data) | ||
316 | { | ||
317 | struct scatterlist *sg; | ||
318 | int i; | ||
319 | |||
320 | for_each_sg(data->sg, sg, data->sg_len, i) | ||
321 | buffer_swap32(sg_virt(sg), sg->length); | ||
322 | } | ||
323 | #else | ||
324 | static inline void mxcmci_swap_buffers(struct mmc_data *data) {} | ||
325 | #endif | ||
326 | |||
243 | static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | 327 | static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) |
244 | { | 328 | { |
245 | unsigned int nob = data->blocks; | 329 | unsigned int nob = data->blocks; |
@@ -255,8 +339,8 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | |||
255 | host->data = data; | 339 | host->data = data; |
256 | data->bytes_xfered = 0; | 340 | data->bytes_xfered = 0; |
257 | 341 | ||
258 | writew(nob, host->base + MMC_REG_NOB); | 342 | mxcmci_writew(host, nob, MMC_REG_NOB); |
259 | writew(blksz, host->base + MMC_REG_BLK_LEN); | 343 | mxcmci_writew(host, blksz, MMC_REG_BLK_LEN); |
260 | host->datasize = datasize; | 344 | host->datasize = datasize; |
261 | 345 | ||
262 | if (!mxcmci_use_dma(host)) | 346 | if (!mxcmci_use_dma(host)) |
@@ -275,6 +359,8 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | |||
275 | } else { | 359 | } else { |
276 | host->dma_dir = DMA_TO_DEVICE; | 360 | host->dma_dir = DMA_TO_DEVICE; |
277 | slave_dirn = DMA_MEM_TO_DEV; | 361 | slave_dirn = DMA_MEM_TO_DEV; |
362 | |||
363 | mxcmci_swap_buffers(data); | ||
278 | } | 364 | } |
279 | 365 | ||
280 | nents = dma_map_sg(host->dma->device->dev, data->sg, | 366 | nents = dma_map_sg(host->dma->device->dev, data->sg, |
@@ -312,13 +398,13 @@ static void mxcmci_dma_callback(void *data) | |||
312 | 398 | ||
313 | del_timer(&host->watchdog); | 399 | del_timer(&host->watchdog); |
314 | 400 | ||
315 | stat = readl(host->base + MMC_REG_STATUS); | 401 | stat = mxcmci_readl(host, MMC_REG_STATUS); |
316 | writel(stat & ~STATUS_DATA_TRANS_DONE, host->base + MMC_REG_STATUS); | 402 | mxcmci_writel(host, stat & ~STATUS_DATA_TRANS_DONE, MMC_REG_STATUS); |
317 | 403 | ||
318 | dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); | 404 | dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); |
319 | 405 | ||
320 | if (stat & STATUS_READ_OP_DONE) | 406 | if (stat & STATUS_READ_OP_DONE) |
321 | writel(STATUS_READ_OP_DONE, host->base + MMC_REG_STATUS); | 407 | mxcmci_writel(host, STATUS_READ_OP_DONE, MMC_REG_STATUS); |
322 | 408 | ||
323 | mxcmci_data_done(host, stat); | 409 | mxcmci_data_done(host, stat); |
324 | } | 410 | } |
@@ -366,12 +452,12 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, | |||
366 | spin_lock_irqsave(&host->lock, flags); | 452 | spin_lock_irqsave(&host->lock, flags); |
367 | if (host->use_sdio) | 453 | if (host->use_sdio) |
368 | int_cntr |= INT_SDIO_IRQ_EN; | 454 | int_cntr |= INT_SDIO_IRQ_EN; |
369 | writel(int_cntr, host->base + MMC_REG_INT_CNTR); | 455 | mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR); |
370 | spin_unlock_irqrestore(&host->lock, flags); | 456 | spin_unlock_irqrestore(&host->lock, flags); |
371 | 457 | ||
372 | writew(cmd->opcode, host->base + MMC_REG_CMD); | 458 | mxcmci_writew(host, cmd->opcode, MMC_REG_CMD); |
373 | writel(cmd->arg, host->base + MMC_REG_ARG); | 459 | mxcmci_writel(host, cmd->arg, MMC_REG_ARG); |
374 | writew(cmdat, host->base + MMC_REG_CMD_DAT_CONT); | 460 | mxcmci_writew(host, cmdat, MMC_REG_CMD_DAT_CONT); |
375 | 461 | ||
376 | return 0; | 462 | return 0; |
377 | } | 463 | } |
@@ -385,7 +471,7 @@ static void mxcmci_finish_request(struct mxcmci_host *host, | |||
385 | spin_lock_irqsave(&host->lock, flags); | 471 | spin_lock_irqsave(&host->lock, flags); |
386 | if (host->use_sdio) | 472 | if (host->use_sdio) |
387 | int_cntr |= INT_SDIO_IRQ_EN; | 473 | int_cntr |= INT_SDIO_IRQ_EN; |
388 | writel(int_cntr, host->base + MMC_REG_INT_CNTR); | 474 | mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR); |
389 | spin_unlock_irqrestore(&host->lock, flags); | 475 | spin_unlock_irqrestore(&host->lock, flags); |
390 | 476 | ||
391 | host->req = NULL; | 477 | host->req = NULL; |
@@ -400,9 +486,11 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat) | |||
400 | struct mmc_data *data = host->data; | 486 | struct mmc_data *data = host->data; |
401 | int data_error; | 487 | int data_error; |
402 | 488 | ||
403 | if (mxcmci_use_dma(host)) | 489 | if (mxcmci_use_dma(host)) { |
404 | dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, | 490 | dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, |
405 | host->dma_dir); | 491 | host->dma_dir); |
492 | mxcmci_swap_buffers(data); | ||
493 | } | ||
406 | 494 | ||
407 | if (stat & STATUS_ERR_MASK) { | 495 | if (stat & STATUS_ERR_MASK) { |
408 | dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", | 496 | dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", |
@@ -460,14 +548,14 @@ static void mxcmci_read_response(struct mxcmci_host *host, unsigned int stat) | |||
460 | if (cmd->flags & MMC_RSP_PRESENT) { | 548 | if (cmd->flags & MMC_RSP_PRESENT) { |
461 | if (cmd->flags & MMC_RSP_136) { | 549 | if (cmd->flags & MMC_RSP_136) { |
462 | for (i = 0; i < 4; i++) { | 550 | for (i = 0; i < 4; i++) { |
463 | a = readw(host->base + MMC_REG_RES_FIFO); | 551 | a = mxcmci_readw(host, MMC_REG_RES_FIFO); |
464 | b = readw(host->base + MMC_REG_RES_FIFO); | 552 | b = mxcmci_readw(host, MMC_REG_RES_FIFO); |
465 | cmd->resp[i] = a << 16 | b; | 553 | cmd->resp[i] = a << 16 | b; |
466 | } | 554 | } |
467 | } else { | 555 | } else { |
468 | a = readw(host->base + MMC_REG_RES_FIFO); | 556 | a = mxcmci_readw(host, MMC_REG_RES_FIFO); |
469 | b = readw(host->base + MMC_REG_RES_FIFO); | 557 | b = mxcmci_readw(host, MMC_REG_RES_FIFO); |
470 | c = readw(host->base + MMC_REG_RES_FIFO); | 558 | c = mxcmci_readw(host, MMC_REG_RES_FIFO); |
471 | cmd->resp[0] = a << 24 | b << 8 | c >> 8; | 559 | cmd->resp[0] = a << 24 | b << 8 | c >> 8; |
472 | } | 560 | } |
473 | } | 561 | } |
@@ -479,7 +567,7 @@ static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask) | |||
479 | unsigned long timeout = jiffies + HZ; | 567 | unsigned long timeout = jiffies + HZ; |
480 | 568 | ||
481 | do { | 569 | do { |
482 | stat = readl(host->base + MMC_REG_STATUS); | 570 | stat = mxcmci_readl(host, MMC_REG_STATUS); |
483 | if (stat & STATUS_ERR_MASK) | 571 | if (stat & STATUS_ERR_MASK) |
484 | return stat; | 572 | return stat; |
485 | if (time_after(jiffies, timeout)) { | 573 | if (time_after(jiffies, timeout)) { |
@@ -503,7 +591,7 @@ static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes) | |||
503 | STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE); | 591 | STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE); |
504 | if (stat) | 592 | if (stat) |
505 | return stat; | 593 | return stat; |
506 | *buf++ = readl(host->base + MMC_REG_BUFFER_ACCESS); | 594 | *buf++ = cpu_to_le32(mxcmci_readl(host, MMC_REG_BUFFER_ACCESS)); |
507 | bytes -= 4; | 595 | bytes -= 4; |
508 | } | 596 | } |
509 | 597 | ||
@@ -515,7 +603,7 @@ static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes) | |||
515 | STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE); | 603 | STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE); |
516 | if (stat) | 604 | if (stat) |
517 | return stat; | 605 | return stat; |
518 | tmp = readl(host->base + MMC_REG_BUFFER_ACCESS); | 606 | tmp = cpu_to_le32(mxcmci_readl(host, MMC_REG_BUFFER_ACCESS)); |
519 | memcpy(b, &tmp, bytes); | 607 | memcpy(b, &tmp, bytes); |
520 | } | 608 | } |
521 | 609 | ||
@@ -531,7 +619,7 @@ static int mxcmci_push(struct mxcmci_host *host, void *_buf, int bytes) | |||
531 | stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); | 619 | stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); |
532 | if (stat) | 620 | if (stat) |
533 | return stat; | 621 | return stat; |
534 | writel(*buf++, host->base + MMC_REG_BUFFER_ACCESS); | 622 | mxcmci_writel(host, cpu_to_le32(*buf++), MMC_REG_BUFFER_ACCESS); |
535 | bytes -= 4; | 623 | bytes -= 4; |
536 | } | 624 | } |
537 | 625 | ||
@@ -544,7 +632,7 @@ static int mxcmci_push(struct mxcmci_host *host, void *_buf, int bytes) | |||
544 | return stat; | 632 | return stat; |
545 | 633 | ||
546 | memcpy(&tmp, b, bytes); | 634 | memcpy(&tmp, b, bytes); |
547 | writel(tmp, host->base + MMC_REG_BUFFER_ACCESS); | 635 | mxcmci_writel(host, cpu_to_le32(tmp), MMC_REG_BUFFER_ACCESS); |
548 | } | 636 | } |
549 | 637 | ||
550 | stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); | 638 | stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); |
@@ -590,8 +678,8 @@ static void mxcmci_datawork(struct work_struct *work) | |||
590 | datawork); | 678 | datawork); |
591 | int datastat = mxcmci_transfer_data(host); | 679 | int datastat = mxcmci_transfer_data(host); |
592 | 680 | ||
593 | writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, | 681 | mxcmci_writel(host, STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, |
594 | host->base + MMC_REG_STATUS); | 682 | MMC_REG_STATUS); |
595 | mxcmci_finish_data(host, datastat); | 683 | mxcmci_finish_data(host, datastat); |
596 | 684 | ||
597 | if (host->req->stop) { | 685 | if (host->req->stop) { |
@@ -606,24 +694,40 @@ static void mxcmci_datawork(struct work_struct *work) | |||
606 | 694 | ||
607 | static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat) | 695 | static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat) |
608 | { | 696 | { |
609 | struct mmc_data *data = host->data; | 697 | struct mmc_request *req; |
610 | int data_error; | 698 | int data_error; |
699 | unsigned long flags; | ||
700 | |||
701 | spin_lock_irqsave(&host->lock, flags); | ||
702 | |||
703 | if (!host->data) { | ||
704 | spin_unlock_irqrestore(&host->lock, flags); | ||
705 | return; | ||
706 | } | ||
611 | 707 | ||
612 | if (!data) | 708 | if (!host->req) { |
709 | spin_unlock_irqrestore(&host->lock, flags); | ||
613 | return; | 710 | return; |
711 | } | ||
712 | |||
713 | req = host->req; | ||
714 | if (!req->stop) | ||
715 | host->req = NULL; /* we will handle finish req below */ | ||
614 | 716 | ||
615 | data_error = mxcmci_finish_data(host, stat); | 717 | data_error = mxcmci_finish_data(host, stat); |
616 | 718 | ||
719 | spin_unlock_irqrestore(&host->lock, flags); | ||
720 | |||
617 | mxcmci_read_response(host, stat); | 721 | mxcmci_read_response(host, stat); |
618 | host->cmd = NULL; | 722 | host->cmd = NULL; |
619 | 723 | ||
620 | if (host->req->stop) { | 724 | if (req->stop) { |
621 | if (mxcmci_start_cmd(host, host->req->stop, 0)) { | 725 | if (mxcmci_start_cmd(host, req->stop, 0)) { |
622 | mxcmci_finish_request(host, host->req); | 726 | mxcmci_finish_request(host, req); |
623 | return; | 727 | return; |
624 | } | 728 | } |
625 | } else { | 729 | } else { |
626 | mxcmci_finish_request(host, host->req); | 730 | mxcmci_finish_request(host, req); |
627 | } | 731 | } |
628 | } | 732 | } |
629 | 733 | ||
@@ -653,9 +757,11 @@ static irqreturn_t mxcmci_irq(int irq, void *devid) | |||
653 | bool sdio_irq; | 757 | bool sdio_irq; |
654 | u32 stat; | 758 | u32 stat; |
655 | 759 | ||
656 | stat = readl(host->base + MMC_REG_STATUS); | 760 | stat = mxcmci_readl(host, MMC_REG_STATUS); |
657 | writel(stat & ~(STATUS_SDIO_INT_ACTIVE | STATUS_DATA_TRANS_DONE | | 761 | mxcmci_writel(host, |
658 | STATUS_WRITE_OP_DONE), host->base + MMC_REG_STATUS); | 762 | stat & ~(STATUS_SDIO_INT_ACTIVE | STATUS_DATA_TRANS_DONE | |
763 | STATUS_WRITE_OP_DONE), | ||
764 | MMC_REG_STATUS); | ||
659 | 765 | ||
660 | dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); | 766 | dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); |
661 | 767 | ||
@@ -665,11 +771,11 @@ static irqreturn_t mxcmci_irq(int irq, void *devid) | |||
665 | 771 | ||
666 | if (mxcmci_use_dma(host) && | 772 | if (mxcmci_use_dma(host) && |
667 | (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE))) | 773 | (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE))) |
668 | writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, | 774 | mxcmci_writel(host, STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, |
669 | host->base + MMC_REG_STATUS); | 775 | MMC_REG_STATUS); |
670 | 776 | ||
671 | if (sdio_irq) { | 777 | if (sdio_irq) { |
672 | writel(STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS); | 778 | mxcmci_writel(host, STATUS_SDIO_INT_ACTIVE, MMC_REG_STATUS); |
673 | mmc_signal_sdio_irq(host->mmc); | 779 | mmc_signal_sdio_irq(host->mmc); |
674 | } | 780 | } |
675 | 781 | ||
@@ -751,7 +857,7 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios) | |||
751 | prescaler <<= 1; | 857 | prescaler <<= 1; |
752 | } | 858 | } |
753 | 859 | ||
754 | writew((prescaler << 4) | divider, host->base + MMC_REG_CLK_RATE); | 860 | mxcmci_writew(host, (prescaler << 4) | divider, MMC_REG_CLK_RATE); |
755 | 861 | ||
756 | dev_dbg(mmc_dev(host->mmc), "scaler: %d divider: %d in: %d out: %d\n", | 862 | dev_dbg(mmc_dev(host->mmc), "scaler: %d divider: %d in: %d out: %d\n", |
757 | prescaler, divider, clk_in, clk_ios); | 863 | prescaler, divider, clk_in, clk_ios); |
@@ -814,9 +920,9 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
814 | 920 | ||
815 | if (ios->clock) { | 921 | if (ios->clock) { |
816 | mxcmci_set_clk_rate(host, ios->clock); | 922 | mxcmci_set_clk_rate(host, ios->clock); |
817 | writew(STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK); | 923 | mxcmci_writew(host, STR_STP_CLK_START_CLK, MMC_REG_STR_STP_CLK); |
818 | } else { | 924 | } else { |
819 | writew(STR_STP_CLK_STOP_CLK, host->base + MMC_REG_STR_STP_CLK); | 925 | mxcmci_writew(host, STR_STP_CLK_STOP_CLK, MMC_REG_STR_STP_CLK); |
820 | } | 926 | } |
821 | 927 | ||
822 | host->clock = ios->clock; | 928 | host->clock = ios->clock; |
@@ -839,10 +945,11 @@ static int mxcmci_get_ro(struct mmc_host *mmc) | |||
839 | if (host->pdata && host->pdata->get_ro) | 945 | if (host->pdata && host->pdata->get_ro) |
840 | return !!host->pdata->get_ro(mmc_dev(mmc)); | 946 | return !!host->pdata->get_ro(mmc_dev(mmc)); |
841 | /* | 947 | /* |
842 | * Board doesn't support read only detection; let the mmc core | 948 | * If board doesn't support read only detection (no mmc_gpio |
843 | * decide what to do. | 949 | * context or gpio is invalid), then let the mmc core decide |
950 | * what to do. | ||
844 | */ | 951 | */ |
845 | return -ENOSYS; | 952 | return mmc_gpio_get_ro(mmc); |
846 | } | 953 | } |
847 | 954 | ||
848 | static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable) | 955 | static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable) |
@@ -853,14 +960,14 @@ static void mxcmci_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
853 | 960 | ||
854 | spin_lock_irqsave(&host->lock, flags); | 961 | spin_lock_irqsave(&host->lock, flags); |
855 | host->use_sdio = enable; | 962 | host->use_sdio = enable; |
856 | int_cntr = readl(host->base + MMC_REG_INT_CNTR); | 963 | int_cntr = mxcmci_readl(host, MMC_REG_INT_CNTR); |
857 | 964 | ||
858 | if (enable) | 965 | if (enable) |
859 | int_cntr |= INT_SDIO_IRQ_EN; | 966 | int_cntr |= INT_SDIO_IRQ_EN; |
860 | else | 967 | else |
861 | int_cntr &= ~INT_SDIO_IRQ_EN; | 968 | int_cntr &= ~INT_SDIO_IRQ_EN; |
862 | 969 | ||
863 | writel(int_cntr, host->base + MMC_REG_INT_CNTR); | 970 | mxcmci_writel(host, int_cntr, MMC_REG_INT_CNTR); |
864 | spin_unlock_irqrestore(&host->lock, flags); | 971 | spin_unlock_irqrestore(&host->lock, flags); |
865 | } | 972 | } |
866 | 973 | ||
@@ -898,7 +1005,7 @@ static void mxcmci_watchdog(unsigned long data) | |||
898 | struct mmc_host *mmc = (struct mmc_host *)data; | 1005 | struct mmc_host *mmc = (struct mmc_host *)data; |
899 | struct mxcmci_host *host = mmc_priv(mmc); | 1006 | struct mxcmci_host *host = mmc_priv(mmc); |
900 | struct mmc_request *req = host->req; | 1007 | struct mmc_request *req = host->req; |
901 | unsigned int stat = readl(host->base + MMC_REG_STATUS); | 1008 | unsigned int stat = mxcmci_readl(host, MMC_REG_STATUS); |
902 | 1009 | ||
903 | if (host->dma_dir == DMA_FROM_DEVICE) { | 1010 | if (host->dma_dir == DMA_FROM_DEVICE) { |
904 | dmaengine_terminate_all(host->dma); | 1011 | dmaengine_terminate_all(host->dma); |
@@ -914,7 +1021,8 @@ static void mxcmci_watchdog(unsigned long data) | |||
914 | 1021 | ||
915 | /* Mark transfer as erroneus and inform the upper layers */ | 1022 | /* Mark transfer as erroneus and inform the upper layers */ |
916 | 1023 | ||
917 | host->data->error = -ETIMEDOUT; | 1024 | if (host->data) |
1025 | host->data->error = -ETIMEDOUT; | ||
918 | host->req = NULL; | 1026 | host->req = NULL; |
919 | host->cmd = NULL; | 1027 | host->cmd = NULL; |
920 | host->data = NULL; | 1028 | host->data = NULL; |
@@ -935,9 +1043,14 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
935 | struct mxcmci_host *host = NULL; | 1043 | struct mxcmci_host *host = NULL; |
936 | struct resource *iores, *r; | 1044 | struct resource *iores, *r; |
937 | int ret = 0, irq; | 1045 | int ret = 0, irq; |
1046 | bool dat3_card_detect = false; | ||
938 | dma_cap_mask_t mask; | 1047 | dma_cap_mask_t mask; |
1048 | const struct of_device_id *of_id; | ||
1049 | struct imxmmc_platform_data *pdata = pdev->dev.platform_data; | ||
939 | 1050 | ||
940 | pr_info("i.MX SDHC driver\n"); | 1051 | pr_info("i.MX/MPC512x SDHC driver\n"); |
1052 | |||
1053 | of_id = of_match_device(mxcmci_of_match, &pdev->dev); | ||
941 | 1054 | ||
942 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1055 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
943 | irq = platform_get_irq(pdev, 0); | 1056 | irq = platform_get_irq(pdev, 0); |
@@ -954,11 +1067,16 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
954 | goto out_release_mem; | 1067 | goto out_release_mem; |
955 | } | 1068 | } |
956 | 1069 | ||
1070 | mmc_of_parse(mmc); | ||
957 | mmc->ops = &mxcmci_ops; | 1071 | mmc->ops = &mxcmci_ops; |
958 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | 1072 | |
1073 | /* For devicetree parsing, the bus width is read from devicetree */ | ||
1074 | if (pdata) | ||
1075 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | ||
1076 | else | ||
1077 | mmc->caps |= MMC_CAP_SDIO_IRQ; | ||
959 | 1078 | ||
960 | /* MMC core transfer sizes tunable parameters */ | 1079 | /* MMC core transfer sizes tunable parameters */ |
961 | mmc->max_segs = 64; | ||
962 | mmc->max_blk_size = 2048; | 1080 | mmc->max_blk_size = 2048; |
963 | mmc->max_blk_count = 65535; | 1081 | mmc->max_blk_count = 65535; |
964 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 1082 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
@@ -971,14 +1089,30 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
971 | goto out_free; | 1089 | goto out_free; |
972 | } | 1090 | } |
973 | 1091 | ||
1092 | if (of_id) { | ||
1093 | const struct platform_device_id *id_entry = of_id->data; | ||
1094 | host->devtype = id_entry->driver_data; | ||
1095 | } else { | ||
1096 | host->devtype = pdev->id_entry->driver_data; | ||
1097 | } | ||
1098 | |||
1099 | /* adjust max_segs after devtype detection */ | ||
1100 | if (!is_mpc512x_mmc(host)) | ||
1101 | mmc->max_segs = 64; | ||
1102 | |||
974 | host->mmc = mmc; | 1103 | host->mmc = mmc; |
975 | host->pdata = pdev->dev.platform_data; | 1104 | host->pdata = pdata; |
976 | host->devtype = pdev->id_entry->driver_data; | ||
977 | spin_lock_init(&host->lock); | 1105 | spin_lock_init(&host->lock); |
978 | 1106 | ||
1107 | if (pdata) | ||
1108 | dat3_card_detect = pdata->dat3_card_detect; | ||
1109 | else if (!(mmc->caps & MMC_CAP_NONREMOVABLE) | ||
1110 | && !of_property_read_bool(pdev->dev.of_node, "cd-gpios")) | ||
1111 | dat3_card_detect = true; | ||
1112 | |||
979 | mxcmci_init_ocr(host); | 1113 | mxcmci_init_ocr(host); |
980 | 1114 | ||
981 | if (host->pdata && host->pdata->dat3_card_detect) | 1115 | if (dat3_card_detect) |
982 | host->default_irq_mask = | 1116 | host->default_irq_mask = |
983 | INT_CARD_INSERTION_EN | INT_CARD_REMOVAL_EN; | 1117 | INT_CARD_INSERTION_EN | INT_CARD_REMOVAL_EN; |
984 | else | 1118 | else |
@@ -1004,7 +1138,7 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
1004 | 1138 | ||
1005 | mxcmci_softreset(host); | 1139 | mxcmci_softreset(host); |
1006 | 1140 | ||
1007 | host->rev_no = readw(host->base + MMC_REG_REV_NO); | 1141 | host->rev_no = mxcmci_readw(host, MMC_REG_REV_NO); |
1008 | if (host->rev_no != 0x400) { | 1142 | if (host->rev_no != 0x400) { |
1009 | ret = -ENODEV; | 1143 | ret = -ENODEV; |
1010 | dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n", | 1144 | dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n", |
@@ -1016,25 +1150,28 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
1016 | mmc->f_max = clk_get_rate(host->clk_per) >> 1; | 1150 | mmc->f_max = clk_get_rate(host->clk_per) >> 1; |
1017 | 1151 | ||
1018 | /* recommended in data sheet */ | 1152 | /* recommended in data sheet */ |
1019 | writew(0x2db4, host->base + MMC_REG_READ_TO); | 1153 | mxcmci_writew(host, 0x2db4, MMC_REG_READ_TO); |
1020 | 1154 | ||
1021 | writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR); | 1155 | mxcmci_writel(host, host->default_irq_mask, MMC_REG_INT_CNTR); |
1022 | |||
1023 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
1024 | if (r) { | ||
1025 | host->dmareq = r->start; | ||
1026 | host->dma_data.peripheral_type = IMX_DMATYPE_SDHC; | ||
1027 | host->dma_data.priority = DMA_PRIO_LOW; | ||
1028 | host->dma_data.dma_request = host->dmareq; | ||
1029 | dma_cap_zero(mask); | ||
1030 | dma_cap_set(DMA_SLAVE, mask); | ||
1031 | host->dma = dma_request_channel(mask, filter, host); | ||
1032 | if (host->dma) | ||
1033 | mmc->max_seg_size = dma_get_max_seg_size( | ||
1034 | host->dma->device->dev); | ||
1035 | } | ||
1036 | 1156 | ||
1037 | if (!host->dma) | 1157 | if (!host->pdata) { |
1158 | host->dma = dma_request_slave_channel(&pdev->dev, "rx-tx"); | ||
1159 | } else { | ||
1160 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
1161 | if (r) { | ||
1162 | host->dmareq = r->start; | ||
1163 | host->dma_data.peripheral_type = IMX_DMATYPE_SDHC; | ||
1164 | host->dma_data.priority = DMA_PRIO_LOW; | ||
1165 | host->dma_data.dma_request = host->dmareq; | ||
1166 | dma_cap_zero(mask); | ||
1167 | dma_cap_set(DMA_SLAVE, mask); | ||
1168 | host->dma = dma_request_channel(mask, filter, host); | ||
1169 | } | ||
1170 | } | ||
1171 | if (host->dma) | ||
1172 | mmc->max_seg_size = dma_get_max_seg_size( | ||
1173 | host->dma->device->dev); | ||
1174 | else | ||
1038 | dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n"); | 1175 | dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n"); |
1039 | 1176 | ||
1040 | INIT_WORK(&host->datawork, mxcmci_datawork); | 1177 | INIT_WORK(&host->datawork, mxcmci_datawork); |
@@ -1052,12 +1189,12 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
1052 | goto out_free_irq; | 1189 | goto out_free_irq; |
1053 | } | 1190 | } |
1054 | 1191 | ||
1055 | mmc_add_host(mmc); | ||
1056 | |||
1057 | init_timer(&host->watchdog); | 1192 | init_timer(&host->watchdog); |
1058 | host->watchdog.function = &mxcmci_watchdog; | 1193 | host->watchdog.function = &mxcmci_watchdog; |
1059 | host->watchdog.data = (unsigned long)mmc; | 1194 | host->watchdog.data = (unsigned long)mmc; |
1060 | 1195 | ||
1196 | mmc_add_host(mmc); | ||
1197 | |||
1061 | return 0; | 1198 | return 0; |
1062 | 1199 | ||
1063 | out_free_irq: | 1200 | out_free_irq: |
@@ -1153,6 +1290,7 @@ static struct platform_driver mxcmci_driver = { | |||
1153 | #ifdef CONFIG_PM | 1290 | #ifdef CONFIG_PM |
1154 | .pm = &mxcmci_pm_ops, | 1291 | .pm = &mxcmci_pm_ops, |
1155 | #endif | 1292 | #endif |
1293 | .of_match_table = mxcmci_of_match, | ||
1156 | } | 1294 | } |
1157 | }; | 1295 | }; |
1158 | 1296 | ||
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 4efe3021b217..146a53bfab71 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c | |||
@@ -72,6 +72,9 @@ struct mxs_mmc_host { | |||
72 | int sdio_irq_en; | 72 | int sdio_irq_en; |
73 | int wp_gpio; | 73 | int wp_gpio; |
74 | bool wp_inverted; | 74 | bool wp_inverted; |
75 | bool cd_inverted; | ||
76 | bool broken_cd; | ||
77 | bool non_removable; | ||
75 | }; | 78 | }; |
76 | 79 | ||
77 | static int mxs_mmc_get_ro(struct mmc_host *mmc) | 80 | static int mxs_mmc_get_ro(struct mmc_host *mmc) |
@@ -95,8 +98,9 @@ static int mxs_mmc_get_cd(struct mmc_host *mmc) | |||
95 | struct mxs_mmc_host *host = mmc_priv(mmc); | 98 | struct mxs_mmc_host *host = mmc_priv(mmc); |
96 | struct mxs_ssp *ssp = &host->ssp; | 99 | struct mxs_ssp *ssp = &host->ssp; |
97 | 100 | ||
98 | return !(readl(ssp->base + HW_SSP_STATUS(ssp)) & | 101 | return host->non_removable || host->broken_cd || |
99 | BM_SSP_STATUS_CARD_DETECT); | 102 | !(readl(ssp->base + HW_SSP_STATUS(ssp)) & |
103 | BM_SSP_STATUS_CARD_DETECT) ^ host->cd_inverted; | ||
100 | } | 104 | } |
101 | 105 | ||
102 | static void mxs_mmc_reset(struct mxs_mmc_host *host) | 106 | static void mxs_mmc_reset(struct mxs_mmc_host *host) |
@@ -686,11 +690,16 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
686 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 690 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
687 | else if (bus_width == 8) | 691 | else if (bus_width == 8) |
688 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; | 692 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; |
693 | host->broken_cd = of_property_read_bool(np, "broken-cd"); | ||
694 | host->non_removable = of_property_read_bool(np, "non-removable"); | ||
695 | if (host->non_removable) | ||
696 | mmc->caps |= MMC_CAP_NONREMOVABLE; | ||
689 | host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags); | 697 | host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags); |
690 | |||
691 | if (flags & OF_GPIO_ACTIVE_LOW) | 698 | if (flags & OF_GPIO_ACTIVE_LOW) |
692 | host->wp_inverted = 1; | 699 | host->wp_inverted = 1; |
693 | 700 | ||
701 | host->cd_inverted = of_property_read_bool(np, "cd-inverted"); | ||
702 | |||
694 | mmc->f_min = 400000; | 703 | mmc->f_min = 400000; |
695 | mmc->f_max = 288000000; | 704 | mmc->f_max = 288000000; |
696 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 705 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index bc5807873b2c..6e44025acf01 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -1717,6 +1717,12 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) | |||
1717 | struct omap_mmc_platform_data *pdata; | 1717 | struct omap_mmc_platform_data *pdata; |
1718 | struct device_node *np = dev->of_node; | 1718 | struct device_node *np = dev->of_node; |
1719 | u32 bus_width, max_freq; | 1719 | u32 bus_width, max_freq; |
1720 | int cd_gpio, wp_gpio; | ||
1721 | |||
1722 | cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); | ||
1723 | wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); | ||
1724 | if (cd_gpio == -EPROBE_DEFER || wp_gpio == -EPROBE_DEFER) | ||
1725 | return ERR_PTR(-EPROBE_DEFER); | ||
1720 | 1726 | ||
1721 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 1727 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
1722 | if (!pdata) | 1728 | if (!pdata) |
@@ -1727,8 +1733,8 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) | |||
1727 | 1733 | ||
1728 | /* This driver only supports 1 slot */ | 1734 | /* This driver only supports 1 slot */ |
1729 | pdata->nr_slots = 1; | 1735 | pdata->nr_slots = 1; |
1730 | pdata->slots[0].switch_pin = of_get_named_gpio(np, "cd-gpios", 0); | 1736 | pdata->slots[0].switch_pin = cd_gpio; |
1731 | pdata->slots[0].gpio_wp = of_get_named_gpio(np, "wp-gpios", 0); | 1737 | pdata->slots[0].gpio_wp = wp_gpio; |
1732 | 1738 | ||
1733 | if (of_find_property(np, "ti,non-removable", NULL)) { | 1739 | if (of_find_property(np, "ti,non-removable", NULL)) { |
1734 | pdata->slots[0].nonremovable = true; | 1740 | pdata->slots[0].nonremovable = true; |
@@ -1774,6 +1780,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
1774 | match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); | 1780 | match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); |
1775 | if (match) { | 1781 | if (match) { |
1776 | pdata = of_get_hsmmc_pdata(&pdev->dev); | 1782 | pdata = of_get_hsmmc_pdata(&pdev->dev); |
1783 | |||
1784 | if (IS_ERR(pdata)) | ||
1785 | return PTR_ERR(pdata); | ||
1786 | |||
1777 | if (match->data) { | 1787 | if (match->data) { |
1778 | const u16 *offsetp = match->data; | 1788 | const u16 *offsetp = match->data; |
1779 | pdata->reg_offset = *offsetp; | 1789 | pdata->reg_offset = *offsetp; |
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index f981f7d1f6e3..ad13f4240c49 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c | |||
@@ -57,6 +57,9 @@ struct realtek_pci_sdmmc { | |||
57 | bool eject; | 57 | bool eject; |
58 | bool initial_mode; | 58 | bool initial_mode; |
59 | bool ddr_mode; | 59 | bool ddr_mode; |
60 | int power_state; | ||
61 | #define SDMMC_POWER_ON 1 | ||
62 | #define SDMMC_POWER_OFF 0 | ||
60 | }; | 63 | }; |
61 | 64 | ||
62 | static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) | 65 | static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) |
@@ -765,6 +768,9 @@ static int sd_power_on(struct realtek_pci_sdmmc *host) | |||
765 | struct rtsx_pcr *pcr = host->pcr; | 768 | struct rtsx_pcr *pcr = host->pcr; |
766 | int err; | 769 | int err; |
767 | 770 | ||
771 | if (host->power_state == SDMMC_POWER_ON) | ||
772 | return 0; | ||
773 | |||
768 | rtsx_pci_init_cmd(pcr); | 774 | rtsx_pci_init_cmd(pcr); |
769 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL); | 775 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL); |
770 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE, | 776 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE, |
@@ -787,6 +793,7 @@ static int sd_power_on(struct realtek_pci_sdmmc *host) | |||
787 | if (err < 0) | 793 | if (err < 0) |
788 | return err; | 794 | return err; |
789 | 795 | ||
796 | host->power_state = SDMMC_POWER_ON; | ||
790 | return 0; | 797 | return 0; |
791 | } | 798 | } |
792 | 799 | ||
@@ -795,6 +802,8 @@ static int sd_power_off(struct realtek_pci_sdmmc *host) | |||
795 | struct rtsx_pcr *pcr = host->pcr; | 802 | struct rtsx_pcr *pcr = host->pcr; |
796 | int err; | 803 | int err; |
797 | 804 | ||
805 | host->power_state = SDMMC_POWER_OFF; | ||
806 | |||
798 | rtsx_pci_init_cmd(pcr); | 807 | rtsx_pci_init_cmd(pcr); |
799 | 808 | ||
800 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0); | 809 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0); |
@@ -1260,6 +1269,7 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) | |||
1260 | host->pcr = pcr; | 1269 | host->pcr = pcr; |
1261 | host->mmc = mmc; | 1270 | host->mmc = mmc; |
1262 | host->pdev = pdev; | 1271 | host->pdev = pdev; |
1272 | host->power_state = SDMMC_POWER_OFF; | ||
1263 | platform_set_drvdata(pdev, host); | 1273 | platform_set_drvdata(pdev, host); |
1264 | pcr->slots[RTSX_SD_CARD].p_dev = pdev; | 1274 | pcr->slots[RTSX_SD_CARD].p_dev = pdev; |
1265 | pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; | 1275 | pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; |
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 2592dddbd965..7bcf74b1a5cd 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c | |||
@@ -195,6 +195,8 @@ static int sdhci_acpi_probe(struct platform_device *pdev) | |||
195 | host->mmc->pm_caps |= c->slot->pm_caps; | 195 | host->mmc->pm_caps |= c->slot->pm_caps; |
196 | } | 196 | } |
197 | 197 | ||
198 | host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; | ||
199 | |||
198 | err = sdhci_add_host(host); | 200 | err = sdhci_add_host(host); |
199 | if (err) | 201 | if (err) |
200 | goto err_free; | 202 | goto err_free; |
diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c index 8ffea05152c6..d49bc958c8ba 100644 --- a/drivers/mmc/host/sdhci-bcm2835.c +++ b/drivers/mmc/host/sdhci-bcm2835.c | |||
@@ -124,7 +124,7 @@ unsigned int bcm2835_sdhci_get_min_clock(struct sdhci_host *host) | |||
124 | return MIN_FREQ; | 124 | return MIN_FREQ; |
125 | } | 125 | } |
126 | 126 | ||
127 | static struct sdhci_ops bcm2835_sdhci_ops = { | 127 | static const struct sdhci_ops bcm2835_sdhci_ops = { |
128 | .write_l = bcm2835_sdhci_writel, | 128 | .write_l = bcm2835_sdhci_writel, |
129 | .write_w = bcm2835_sdhci_writew, | 129 | .write_w = bcm2835_sdhci_writew, |
130 | .write_b = bcm2835_sdhci_writeb, | 130 | .write_b = bcm2835_sdhci_writeb, |
@@ -135,7 +135,7 @@ static struct sdhci_ops bcm2835_sdhci_ops = { | |||
135 | .get_min_clock = bcm2835_sdhci_get_min_clock, | 135 | .get_min_clock = bcm2835_sdhci_get_min_clock, |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static struct sdhci_pltfm_data bcm2835_sdhci_pdata = { | 138 | static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = { |
139 | .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | | 139 | .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | |
140 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK, | 140 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK, |
141 | .ops = &bcm2835_sdhci_ops, | 141 | .ops = &bcm2835_sdhci_ops, |
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c index 6ba8502c1ee2..8ebb6b650f3f 100644 --- a/drivers/mmc/host/sdhci-cns3xxx.c +++ b/drivers/mmc/host/sdhci-cns3xxx.c | |||
@@ -79,12 +79,12 @@ out: | |||
79 | host->clock = clock; | 79 | host->clock = clock; |
80 | } | 80 | } |
81 | 81 | ||
82 | static struct sdhci_ops sdhci_cns3xxx_ops = { | 82 | static const struct sdhci_ops sdhci_cns3xxx_ops = { |
83 | .get_max_clock = sdhci_cns3xxx_get_max_clk, | 83 | .get_max_clock = sdhci_cns3xxx_get_max_clk, |
84 | .set_clock = sdhci_cns3xxx_set_clock, | 84 | .set_clock = sdhci_cns3xxx_set_clock, |
85 | }; | 85 | }; |
86 | 86 | ||
87 | static struct sdhci_pltfm_data sdhci_cns3xxx_pdata = { | 87 | static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = { |
88 | .ops = &sdhci_cns3xxx_ops, | 88 | .ops = &sdhci_cns3xxx_ops, |
89 | .quirks = SDHCI_QUIRK_BROKEN_DMA | | 89 | .quirks = SDHCI_QUIRK_BROKEN_DMA | |
90 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | | 90 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | |
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 169fab91778e..15e7803040f1 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c | |||
@@ -83,12 +83,12 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg) | |||
83 | return ret; | 83 | return ret; |
84 | } | 84 | } |
85 | 85 | ||
86 | static struct sdhci_ops sdhci_dove_ops = { | 86 | static const struct sdhci_ops sdhci_dove_ops = { |
87 | .read_w = sdhci_dove_readw, | 87 | .read_w = sdhci_dove_readw, |
88 | .read_l = sdhci_dove_readl, | 88 | .read_l = sdhci_dove_readl, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | static struct sdhci_pltfm_data sdhci_dove_pdata = { | 91 | static const struct sdhci_pltfm_data sdhci_dove_pdata = { |
92 | .ops = &sdhci_dove_ops, | 92 | .ops = &sdhci_dove_ops, |
93 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | | 93 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | |
94 | SDHCI_QUIRK_NO_BUSY_IRQ | | 94 | SDHCI_QUIRK_NO_BUSY_IRQ | |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 78ac00227c1a..67d6dde2ff19 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
@@ -399,7 +399,7 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width) | |||
399 | return 0; | 399 | return 0; |
400 | } | 400 | } |
401 | 401 | ||
402 | static struct sdhci_ops sdhci_esdhc_ops = { | 402 | static const struct sdhci_ops sdhci_esdhc_ops = { |
403 | .read_l = esdhc_readl_le, | 403 | .read_l = esdhc_readl_le, |
404 | .read_w = esdhc_readw_le, | 404 | .read_w = esdhc_readw_le, |
405 | .write_l = esdhc_writel_le, | 405 | .write_l = esdhc_writel_le, |
@@ -412,7 +412,7 @@ static struct sdhci_ops sdhci_esdhc_ops = { | |||
412 | .platform_bus_width = esdhc_pltfm_bus_width, | 412 | .platform_bus_width = esdhc_pltfm_bus_width, |
413 | }; | 413 | }; |
414 | 414 | ||
415 | static struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { | 415 | static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { |
416 | .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT | 416 | .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT |
417 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | 417 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
418 | | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 418 | | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index f32526d2d966..5e68adc2461e 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
@@ -230,7 +230,7 @@ static void esdhc_of_platform_init(struct sdhci_host *host) | |||
230 | host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; | 230 | host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; |
231 | } | 231 | } |
232 | 232 | ||
233 | static struct sdhci_ops sdhci_esdhc_ops = { | 233 | static const struct sdhci_ops sdhci_esdhc_ops = { |
234 | .read_l = esdhc_readl, | 234 | .read_l = esdhc_readl, |
235 | .read_w = esdhc_readw, | 235 | .read_w = esdhc_readw, |
236 | .read_b = esdhc_readb, | 236 | .read_b = esdhc_readb, |
@@ -249,7 +249,7 @@ static struct sdhci_ops sdhci_esdhc_ops = { | |||
249 | .adma_workaround = esdhci_of_adma_workaround, | 249 | .adma_workaround = esdhci_of_adma_workaround, |
250 | }; | 250 | }; |
251 | 251 | ||
252 | static struct sdhci_pltfm_data sdhci_esdhc_pdata = { | 252 | static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { |
253 | /* | 253 | /* |
254 | * card detection could be handled via GPIO | 254 | * card detection could be handled via GPIO |
255 | * eSDHC cannot support End Attribute in NOP ADMA descriptor | 255 | * eSDHC cannot support End Attribute in NOP ADMA descriptor |
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c index c3d3715ec3d7..200a6a9fa805 100644 --- a/drivers/mmc/host/sdhci-of-hlwd.c +++ b/drivers/mmc/host/sdhci-of-hlwd.c | |||
@@ -51,7 +51,7 @@ static void sdhci_hlwd_writeb(struct sdhci_host *host, u8 val, int reg) | |||
51 | udelay(SDHCI_HLWD_WRITE_DELAY); | 51 | udelay(SDHCI_HLWD_WRITE_DELAY); |
52 | } | 52 | } |
53 | 53 | ||
54 | static struct sdhci_ops sdhci_hlwd_ops = { | 54 | static const struct sdhci_ops sdhci_hlwd_ops = { |
55 | .read_l = sdhci_be32bs_readl, | 55 | .read_l = sdhci_be32bs_readl, |
56 | .read_w = sdhci_be32bs_readw, | 56 | .read_w = sdhci_be32bs_readw, |
57 | .read_b = sdhci_be32bs_readb, | 57 | .read_b = sdhci_be32bs_readb, |
@@ -60,7 +60,7 @@ static struct sdhci_ops sdhci_hlwd_ops = { | |||
60 | .write_b = sdhci_hlwd_writeb, | 60 | .write_b = sdhci_hlwd_writeb, |
61 | }; | 61 | }; |
62 | 62 | ||
63 | static struct sdhci_pltfm_data sdhci_hlwd_pdata = { | 63 | static const struct sdhci_pltfm_data sdhci_hlwd_pdata = { |
64 | .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | | 64 | .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | |
65 | SDHCI_QUIRK_32BIT_DMA_SIZE, | 65 | SDHCI_QUIRK_32BIT_DMA_SIZE, |
66 | .ops = &sdhci_hlwd_ops, | 66 | .ops = &sdhci_hlwd_ops, |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index c7ccf3034dad..0012d3fdc999 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -975,7 +975,7 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host) | |||
975 | usleep_range(300, 1000); | 975 | usleep_range(300, 1000); |
976 | } | 976 | } |
977 | 977 | ||
978 | static struct sdhci_ops sdhci_pci_ops = { | 978 | static const struct sdhci_ops sdhci_pci_ops = { |
979 | .enable_dma = sdhci_pci_enable_dma, | 979 | .enable_dma = sdhci_pci_enable_dma, |
980 | .platform_bus_width = sdhci_pci_bus_width, | 980 | .platform_bus_width = sdhci_pci_bus_width, |
981 | .hw_reset = sdhci_pci_hw_reset, | 981 | .hw_reset = sdhci_pci_hw_reset, |
@@ -1279,6 +1279,8 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( | |||
1279 | } | 1279 | } |
1280 | 1280 | ||
1281 | host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; | 1281 | host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; |
1282 | host->mmc->slotno = slotno; | ||
1283 | host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; | ||
1282 | 1284 | ||
1283 | ret = sdhci_add_host(host); | 1285 | ret = sdhci_add_host(host); |
1284 | if (ret) | 1286 | if (ret) |
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 3145a780b035..cd0f1f68e261 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
@@ -44,7 +44,7 @@ unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host) | |||
44 | } | 44 | } |
45 | EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock); | 45 | EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock); |
46 | 46 | ||
47 | static struct sdhci_ops sdhci_pltfm_ops = { | 47 | static const struct sdhci_ops sdhci_pltfm_ops = { |
48 | }; | 48 | }; |
49 | 49 | ||
50 | #ifdef CONFIG_OF | 50 | #ifdef CONFIG_OF |
@@ -94,6 +94,7 @@ void sdhci_get_of_property(struct platform_device *pdev) | |||
94 | 94 | ||
95 | if (of_device_is_compatible(np, "fsl,p2020-esdhc") || | 95 | if (of_device_is_compatible(np, "fsl,p2020-esdhc") || |
96 | of_device_is_compatible(np, "fsl,p1010-esdhc") || | 96 | of_device_is_compatible(np, "fsl,p1010-esdhc") || |
97 | of_device_is_compatible(np, "fsl,t4240-esdhc") || | ||
97 | of_device_is_compatible(np, "fsl,mpc8536-esdhc")) | 98 | of_device_is_compatible(np, "fsl,mpc8536-esdhc")) |
98 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; | 99 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; |
99 | 100 | ||
@@ -114,7 +115,7 @@ void sdhci_get_of_property(struct platform_device *pdev) {} | |||
114 | EXPORT_SYMBOL_GPL(sdhci_get_of_property); | 115 | EXPORT_SYMBOL_GPL(sdhci_get_of_property); |
115 | 116 | ||
116 | struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, | 117 | struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, |
117 | struct sdhci_pltfm_data *pdata) | 118 | const struct sdhci_pltfm_data *pdata) |
118 | { | 119 | { |
119 | struct sdhci_host *host; | 120 | struct sdhci_host *host; |
120 | struct sdhci_pltfm_host *pltfm_host; | 121 | struct sdhci_pltfm_host *pltfm_host; |
@@ -201,7 +202,7 @@ void sdhci_pltfm_free(struct platform_device *pdev) | |||
201 | EXPORT_SYMBOL_GPL(sdhci_pltfm_free); | 202 | EXPORT_SYMBOL_GPL(sdhci_pltfm_free); |
202 | 203 | ||
203 | int sdhci_pltfm_register(struct platform_device *pdev, | 204 | int sdhci_pltfm_register(struct platform_device *pdev, |
204 | struct sdhci_pltfm_data *pdata) | 205 | const struct sdhci_pltfm_data *pdata) |
205 | { | 206 | { |
206 | struct sdhci_host *host; | 207 | struct sdhci_host *host; |
207 | int ret = 0; | 208 | int ret = 0; |
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index 153b6c509ebe..1210ed1b0c60 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h | |||
@@ -16,7 +16,7 @@ | |||
16 | #include "sdhci.h" | 16 | #include "sdhci.h" |
17 | 17 | ||
18 | struct sdhci_pltfm_data { | 18 | struct sdhci_pltfm_data { |
19 | struct sdhci_ops *ops; | 19 | const struct sdhci_ops *ops; |
20 | unsigned int quirks; | 20 | unsigned int quirks; |
21 | }; | 21 | }; |
22 | 22 | ||
@@ -91,11 +91,11 @@ 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); | 91 | extern void sdhci_get_of_property(struct platform_device *pdev); |
92 | 92 | ||
93 | extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, | 93 | extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, |
94 | struct sdhci_pltfm_data *pdata); | 94 | const struct sdhci_pltfm_data *pdata); |
95 | extern void sdhci_pltfm_free(struct platform_device *pdev); | 95 | extern void sdhci_pltfm_free(struct platform_device *pdev); |
96 | 96 | ||
97 | extern int sdhci_pltfm_register(struct platform_device *pdev, | 97 | extern int sdhci_pltfm_register(struct platform_device *pdev, |
98 | struct sdhci_pltfm_data *pdata); | 98 | const struct sdhci_pltfm_data *pdata); |
99 | extern int sdhci_pltfm_unregister(struct platform_device *pdev); | 99 | extern int sdhci_pltfm_unregister(struct platform_device *pdev); |
100 | 100 | ||
101 | extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host); | 101 | extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host); |
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index eeb7d439db1d..6a3f702a38a6 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c | |||
@@ -111,7 +111,7 @@ static int pxav2_mmc_set_width(struct sdhci_host *host, int width) | |||
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
113 | 113 | ||
114 | static struct sdhci_ops pxav2_sdhci_ops = { | 114 | static const struct sdhci_ops pxav2_sdhci_ops = { |
115 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, | 115 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, |
116 | .platform_reset_exit = pxav2_set_private_registers, | 116 | .platform_reset_exit = pxav2_set_private_registers, |
117 | .platform_bus_width = pxav2_mmc_set_width, | 117 | .platform_bus_width = pxav2_mmc_set_width, |
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index a0cdbc570a83..1ae358e0662d 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c | |||
@@ -167,13 +167,21 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) | |||
167 | return 0; | 167 | return 0; |
168 | } | 168 | } |
169 | 169 | ||
170 | static struct sdhci_ops pxav3_sdhci_ops = { | 170 | static const struct sdhci_ops pxav3_sdhci_ops = { |
171 | .platform_reset_exit = pxav3_set_private_registers, | 171 | .platform_reset_exit = pxav3_set_private_registers, |
172 | .set_uhs_signaling = pxav3_set_uhs_signaling, | 172 | .set_uhs_signaling = pxav3_set_uhs_signaling, |
173 | .platform_send_init_74_clocks = pxav3_gen_init_74_clocks, | 173 | .platform_send_init_74_clocks = pxav3_gen_init_74_clocks, |
174 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, | 174 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, |
175 | }; | 175 | }; |
176 | 176 | ||
177 | static struct sdhci_pltfm_data sdhci_pxav3_pdata = { | ||
178 | .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | ||
179 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | ||
180 | | SDHCI_QUIRK_32BIT_ADMA_SIZE | ||
181 | | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, | ||
182 | .ops = &pxav3_sdhci_ops, | ||
183 | }; | ||
184 | |||
177 | #ifdef CONFIG_OF | 185 | #ifdef CONFIG_OF |
178 | static const struct of_device_id sdhci_pxav3_of_match[] = { | 186 | static const struct of_device_id sdhci_pxav3_of_match[] = { |
179 | { | 187 | { |
@@ -187,29 +195,16 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) | |||
187 | { | 195 | { |
188 | struct sdhci_pxa_platdata *pdata; | 196 | struct sdhci_pxa_platdata *pdata; |
189 | struct device_node *np = dev->of_node; | 197 | struct device_node *np = dev->of_node; |
190 | u32 bus_width; | ||
191 | u32 clk_delay_cycles; | 198 | u32 clk_delay_cycles; |
192 | enum of_gpio_flags gpio_flags; | ||
193 | 199 | ||
194 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 200 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
195 | if (!pdata) | 201 | if (!pdata) |
196 | return NULL; | 202 | return NULL; |
197 | 203 | ||
198 | if (of_find_property(np, "non-removable", NULL)) | ||
199 | pdata->flags |= PXA_FLAG_CARD_PERMANENT; | ||
200 | |||
201 | of_property_read_u32(np, "bus-width", &bus_width); | ||
202 | if (bus_width == 8) | ||
203 | pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT; | ||
204 | |||
205 | of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles); | 204 | of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles); |
206 | if (clk_delay_cycles > 0) | 205 | if (clk_delay_cycles > 0) |
207 | pdata->clk_delay_cycles = clk_delay_cycles; | 206 | pdata->clk_delay_cycles = clk_delay_cycles; |
208 | 207 | ||
209 | pdata->ext_cd_gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &gpio_flags); | ||
210 | if (gpio_flags != OF_GPIO_ACTIVE_LOW) | ||
211 | pdata->host_caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; | ||
212 | |||
213 | return pdata; | 208 | return pdata; |
214 | } | 209 | } |
215 | #else | 210 | #else |
@@ -235,7 +230,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
235 | if (!pxa) | 230 | if (!pxa) |
236 | return -ENOMEM; | 231 | return -ENOMEM; |
237 | 232 | ||
238 | host = sdhci_pltfm_init(pdev, NULL); | 233 | host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata); |
239 | if (IS_ERR(host)) { | 234 | if (IS_ERR(host)) { |
240 | kfree(pxa); | 235 | kfree(pxa); |
241 | return PTR_ERR(host); | 236 | return PTR_ERR(host); |
@@ -252,24 +247,18 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
252 | pltfm_host->clk = clk; | 247 | pltfm_host->clk = clk; |
253 | clk_prepare_enable(clk); | 248 | clk_prepare_enable(clk); |
254 | 249 | ||
255 | host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | ||
256 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | ||
257 | | SDHCI_QUIRK_32BIT_ADMA_SIZE | ||
258 | | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN; | ||
259 | |||
260 | /* enable 1/8V DDR capable */ | 250 | /* enable 1/8V DDR capable */ |
261 | host->mmc->caps |= MMC_CAP_1_8V_DDR; | 251 | host->mmc->caps |= MMC_CAP_1_8V_DDR; |
262 | 252 | ||
263 | 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); |
264 | if (match) | 254 | if (match) { |
255 | mmc_of_parse(host->mmc); | ||
256 | sdhci_get_of_property(pdev); | ||
265 | pdata = pxav3_get_mmc_pdata(dev); | 257 | pdata = pxav3_get_mmc_pdata(dev); |
266 | 258 | } else if (pdata) { | |
267 | if (pdata) { | 259 | /* on-chip device */ |
268 | if (pdata->flags & PXA_FLAG_CARD_PERMANENT) { | 260 | if (pdata->flags & PXA_FLAG_CARD_PERMANENT) |
269 | /* on-chip device */ | ||
270 | host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; | ||
271 | host->mmc->caps |= MMC_CAP_NONREMOVABLE; | 261 | host->mmc->caps |= MMC_CAP_NONREMOVABLE; |
272 | } | ||
273 | 262 | ||
274 | /* If slot design supports 8 bit data, indicate this to MMC. */ | 263 | /* If slot design supports 8 bit data, indicate this to MMC. */ |
275 | if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT) | 264 | if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT) |
@@ -296,10 +285,6 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
296 | } | 285 | } |
297 | } | 286 | } |
298 | 287 | ||
299 | host->ops = &pxav3_sdhci_ops; | ||
300 | |||
301 | sdhci_get_of_property(pdev); | ||
302 | |||
303 | pm_runtime_set_active(&pdev->dev); | 288 | pm_runtime_set_active(&pdev->dev); |
304 | pm_runtime_enable(&pdev->dev); | 289 | pm_runtime_enable(&pdev->dev); |
305 | pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS); | 290 | pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS); |
@@ -317,7 +302,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
317 | 302 | ||
318 | platform_set_drvdata(pdev, host); | 303 | platform_set_drvdata(pdev, host); |
319 | 304 | ||
320 | if (pdata->pm_caps & MMC_PM_KEEP_POWER) { | 305 | if (host->mmc->pm_caps & MMC_PM_KEEP_POWER) { |
321 | device_init_wakeup(&pdev->dev, 1); | 306 | device_init_wakeup(&pdev->dev, 1); |
322 | host->mmc->pm_flags |= MMC_PM_WAKE_SDIO_IRQ; | 307 | host->mmc->pm_flags |= MMC_PM_WAKE_SDIO_IRQ; |
323 | } else { | 308 | } else { |
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index e4f52b5c2592..c6f6246a4933 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/of_gpio.h> | 25 | #include <linux/of_gpio.h> |
26 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
27 | #include <linux/pm_runtime.h> | 27 | #include <linux/pm_runtime.h> |
28 | #include <linux/pinctrl/consumer.h> | ||
29 | 28 | ||
30 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
31 | 30 | ||
@@ -44,7 +43,6 @@ | |||
44 | * @ioarea: The resource created when we claimed the IO area. | 43 | * @ioarea: The resource created when we claimed the IO area. |
45 | * @pdata: The platform data for this controller. | 44 | * @pdata: The platform data for this controller. |
46 | * @cur_clk: The index of the current bus clock. | 45 | * @cur_clk: The index of the current bus clock. |
47 | * @gpios: List of gpio numbers parsed from device tree. | ||
48 | * @clk_io: The clock for the internal bus interface. | 46 | * @clk_io: The clock for the internal bus interface. |
49 | * @clk_bus: The clocks that are available for the SD/MMC bus clock. | 47 | * @clk_bus: The clocks that are available for the SD/MMC bus clock. |
50 | */ | 48 | */ |
@@ -56,8 +54,6 @@ struct sdhci_s3c { | |||
56 | unsigned int cur_clk; | 54 | unsigned int cur_clk; |
57 | int ext_cd_irq; | 55 | int ext_cd_irq; |
58 | int ext_cd_gpio; | 56 | int ext_cd_gpio; |
59 | int *gpios; | ||
60 | struct pinctrl *pctrl; | ||
61 | 57 | ||
62 | struct clk *clk_io; | 58 | struct clk *clk_io; |
63 | struct clk *clk_bus[MAX_BUS_CLK]; | 59 | struct clk *clk_bus[MAX_BUS_CLK]; |
@@ -446,88 +442,39 @@ static int sdhci_s3c_parse_dt(struct device *dev, | |||
446 | struct device_node *node = dev->of_node; | 442 | struct device_node *node = dev->of_node; |
447 | struct sdhci_s3c *ourhost = to_s3c(host); | 443 | struct sdhci_s3c *ourhost = to_s3c(host); |
448 | u32 max_width; | 444 | u32 max_width; |
449 | int gpio, cnt, ret; | 445 | int gpio; |
450 | 446 | ||
451 | /* if the bus-width property is not specified, assume width as 1 */ | 447 | /* if the bus-width property is not specified, assume width as 1 */ |
452 | if (of_property_read_u32(node, "bus-width", &max_width)) | 448 | if (of_property_read_u32(node, "bus-width", &max_width)) |
453 | max_width = 1; | 449 | max_width = 1; |
454 | pdata->max_width = max_width; | 450 | pdata->max_width = max_width; |
455 | 451 | ||
456 | ourhost->gpios = devm_kzalloc(dev, NUM_GPIOS(pdata->max_width) * | ||
457 | sizeof(int), GFP_KERNEL); | ||
458 | if (!ourhost->gpios) | ||
459 | return -ENOMEM; | ||
460 | |||
461 | /* get the card detection method */ | 452 | /* get the card detection method */ |
462 | if (of_get_property(node, "broken-cd", NULL)) { | 453 | if (of_get_property(node, "broken-cd", NULL)) { |
463 | pdata->cd_type = S3C_SDHCI_CD_NONE; | 454 | pdata->cd_type = S3C_SDHCI_CD_NONE; |
464 | goto setup_bus; | 455 | return 0; |
465 | } | 456 | } |
466 | 457 | ||
467 | if (of_get_property(node, "non-removable", NULL)) { | 458 | if (of_get_property(node, "non-removable", NULL)) { |
468 | pdata->cd_type = S3C_SDHCI_CD_PERMANENT; | 459 | pdata->cd_type = S3C_SDHCI_CD_PERMANENT; |
469 | goto setup_bus; | 460 | return 0; |
470 | } | 461 | } |
471 | 462 | ||
472 | gpio = of_get_named_gpio(node, "cd-gpios", 0); | 463 | gpio = of_get_named_gpio(node, "cd-gpios", 0); |
473 | if (gpio_is_valid(gpio)) { | 464 | if (gpio_is_valid(gpio)) { |
474 | pdata->cd_type = S3C_SDHCI_CD_GPIO; | 465 | pdata->cd_type = S3C_SDHCI_CD_GPIO; |
475 | goto found_cd; | ||
476 | } else if (gpio != -ENOENT) { | ||
477 | dev_err(dev, "invalid card detect gpio specified\n"); | ||
478 | return -EINVAL; | ||
479 | } | ||
480 | |||
481 | gpio = of_get_named_gpio(node, "samsung,cd-pinmux-gpio", 0); | ||
482 | if (gpio_is_valid(gpio)) { | ||
483 | pdata->cd_type = S3C_SDHCI_CD_INTERNAL; | ||
484 | goto found_cd; | ||
485 | } else if (gpio != -ENOENT) { | ||
486 | dev_err(dev, "invalid card detect gpio specified\n"); | ||
487 | return -EINVAL; | ||
488 | } | ||
489 | |||
490 | /* assuming internal card detect that will be configured by pinctrl */ | ||
491 | pdata->cd_type = S3C_SDHCI_CD_INTERNAL; | ||
492 | goto setup_bus; | ||
493 | |||
494 | found_cd: | ||
495 | if (pdata->cd_type == S3C_SDHCI_CD_GPIO) { | ||
496 | pdata->ext_cd_gpio = gpio; | 466 | pdata->ext_cd_gpio = gpio; |
497 | ourhost->ext_cd_gpio = -1; | 467 | ourhost->ext_cd_gpio = -1; |
498 | if (of_get_property(node, "cd-inverted", NULL)) | 468 | if (of_get_property(node, "cd-inverted", NULL)) |
499 | pdata->ext_cd_gpio_invert = 1; | 469 | pdata->ext_cd_gpio_invert = 1; |
500 | } else if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | ||
501 | ret = devm_gpio_request(dev, gpio, "sdhci-cd"); | ||
502 | if (ret) { | ||
503 | dev_err(dev, "card detect gpio request failed\n"); | ||
504 | return -EINVAL; | ||
505 | } | ||
506 | ourhost->ext_cd_gpio = gpio; | ||
507 | } | ||
508 | |||
509 | setup_bus: | ||
510 | if (!IS_ERR(ourhost->pctrl)) | ||
511 | return 0; | 470 | return 0; |
512 | 471 | } else if (gpio != -ENOENT) { | |
513 | /* get the gpios for command, clock and data lines */ | 472 | dev_err(dev, "invalid card detect gpio specified\n"); |
514 | for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) { | 473 | return -EINVAL; |
515 | gpio = of_get_gpio(node, cnt); | ||
516 | if (!gpio_is_valid(gpio)) { | ||
517 | dev_err(dev, "invalid gpio[%d]\n", cnt); | ||
518 | return -EINVAL; | ||
519 | } | ||
520 | ourhost->gpios[cnt] = gpio; | ||
521 | } | ||
522 | |||
523 | for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) { | ||
524 | ret = devm_gpio_request(dev, ourhost->gpios[cnt], "sdhci-gpio"); | ||
525 | if (ret) { | ||
526 | dev_err(dev, "gpio[%d] request failed\n", cnt); | ||
527 | return -EINVAL; | ||
528 | } | ||
529 | } | 474 | } |
530 | 475 | ||
476 | /* assuming internal card detect that will be configured by pinctrl */ | ||
477 | pdata->cd_type = S3C_SDHCI_CD_INTERNAL; | ||
531 | return 0; | 478 | return 0; |
532 | } | 479 | } |
533 | #else | 480 | #else |
@@ -588,8 +535,6 @@ static int sdhci_s3c_probe(struct platform_device *pdev) | |||
588 | goto err_pdata_io_clk; | 535 | goto err_pdata_io_clk; |
589 | } | 536 | } |
590 | 537 | ||
591 | sc->pctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
592 | |||
593 | if (pdev->dev.of_node) { | 538 | if (pdev->dev.of_node) { |
594 | ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata); | 539 | ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata); |
595 | if (ret) | 540 | if (ret) |
@@ -607,7 +552,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev) | |||
607 | 552 | ||
608 | platform_set_drvdata(pdev, host); | 553 | platform_set_drvdata(pdev, host); |
609 | 554 | ||
610 | sc->clk_io = clk_get(dev, "hsmmc"); | 555 | sc->clk_io = devm_clk_get(dev, "hsmmc"); |
611 | if (IS_ERR(sc->clk_io)) { | 556 | if (IS_ERR(sc->clk_io)) { |
612 | dev_err(dev, "failed to get io clock\n"); | 557 | dev_err(dev, "failed to get io clock\n"); |
613 | ret = PTR_ERR(sc->clk_io); | 558 | ret = PTR_ERR(sc->clk_io); |
@@ -622,7 +567,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev) | |||
622 | char name[14]; | 567 | char name[14]; |
623 | 568 | ||
624 | snprintf(name, 14, "mmc_busclk.%d", ptr); | 569 | snprintf(name, 14, "mmc_busclk.%d", ptr); |
625 | clk = clk_get(dev, name); | 570 | clk = devm_clk_get(dev, name); |
626 | if (IS_ERR(clk)) | 571 | if (IS_ERR(clk)) |
627 | continue; | 572 | continue; |
628 | 573 | ||
@@ -763,15 +708,9 @@ static int sdhci_s3c_probe(struct platform_device *pdev) | |||
763 | #ifndef CONFIG_PM_RUNTIME | 708 | #ifndef CONFIG_PM_RUNTIME |
764 | clk_disable_unprepare(sc->clk_bus[sc->cur_clk]); | 709 | clk_disable_unprepare(sc->clk_bus[sc->cur_clk]); |
765 | #endif | 710 | #endif |
766 | for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { | ||
767 | if (sc->clk_bus[ptr]) { | ||
768 | clk_put(sc->clk_bus[ptr]); | ||
769 | } | ||
770 | } | ||
771 | 711 | ||
772 | err_no_busclks: | 712 | err_no_busclks: |
773 | clk_disable_unprepare(sc->clk_io); | 713 | clk_disable_unprepare(sc->clk_io); |
774 | clk_put(sc->clk_io); | ||
775 | 714 | ||
776 | err_pdata_io_clk: | 715 | err_pdata_io_clk: |
777 | sdhci_free_host(host); | 716 | sdhci_free_host(host); |
@@ -784,7 +723,6 @@ static int sdhci_s3c_remove(struct platform_device *pdev) | |||
784 | struct sdhci_host *host = platform_get_drvdata(pdev); | 723 | struct sdhci_host *host = platform_get_drvdata(pdev); |
785 | struct sdhci_s3c *sc = sdhci_priv(host); | 724 | struct sdhci_s3c *sc = sdhci_priv(host); |
786 | struct s3c_sdhci_platdata *pdata = sc->pdata; | 725 | struct s3c_sdhci_platdata *pdata = sc->pdata; |
787 | int ptr; | ||
788 | 726 | ||
789 | if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup) | 727 | if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup) |
790 | pdata->ext_cd_cleanup(&sdhci_s3c_notify_change); | 728 | pdata->ext_cd_cleanup(&sdhci_s3c_notify_change); |
@@ -804,13 +742,7 @@ static int sdhci_s3c_remove(struct platform_device *pdev) | |||
804 | #ifndef CONFIG_PM_RUNTIME | 742 | #ifndef CONFIG_PM_RUNTIME |
805 | clk_disable_unprepare(sc->clk_bus[sc->cur_clk]); | 743 | clk_disable_unprepare(sc->clk_bus[sc->cur_clk]); |
806 | #endif | 744 | #endif |
807 | for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { | ||
808 | if (sc->clk_bus[ptr]) { | ||
809 | clk_put(sc->clk_bus[ptr]); | ||
810 | } | ||
811 | } | ||
812 | clk_disable_unprepare(sc->clk_io); | 745 | clk_disable_unprepare(sc->clk_io); |
813 | clk_put(sc->clk_io); | ||
814 | 746 | ||
815 | sdhci_free_host(host); | 747 | sdhci_free_host(host); |
816 | platform_set_drvdata(pdev, NULL); | 748 | platform_set_drvdata(pdev, NULL); |
diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c new file mode 100644 index 000000000000..09805af0526d --- /dev/null +++ b/drivers/mmc/host/sdhci-sirf.c | |||
@@ -0,0 +1,193 @@ | |||
1 | /* | ||
2 | * SDHCI support for SiRF primaII and marco SoCs | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/delay.h> | ||
10 | #include <linux/device.h> | ||
11 | #include <linux/mmc/host.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/of.h> | ||
14 | #include <linux/of_gpio.h> | ||
15 | #include <linux/mmc/slot-gpio.h> | ||
16 | #include <linux/pinctrl/consumer.h> | ||
17 | #include "sdhci-pltfm.h" | ||
18 | |||
19 | struct sdhci_sirf_priv { | ||
20 | struct clk *clk; | ||
21 | int gpio_cd; | ||
22 | }; | ||
23 | |||
24 | static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host) | ||
25 | { | ||
26 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
27 | struct sdhci_sirf_priv *priv = pltfm_host->priv; | ||
28 | return clk_get_rate(priv->clk); | ||
29 | } | ||
30 | |||
31 | static struct sdhci_ops sdhci_sirf_ops = { | ||
32 | .get_max_clock = sdhci_sirf_get_max_clk, | ||
33 | }; | ||
34 | |||
35 | static struct sdhci_pltfm_data sdhci_sirf_pdata = { | ||
36 | .ops = &sdhci_sirf_ops, | ||
37 | .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | | ||
38 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | | ||
39 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | | ||
40 | SDHCI_QUIRK_INVERTED_WRITE_PROTECT | | ||
41 | SDHCI_QUIRK_DELAY_AFTER_POWER, | ||
42 | }; | ||
43 | |||
44 | static int sdhci_sirf_probe(struct platform_device *pdev) | ||
45 | { | ||
46 | struct sdhci_host *host; | ||
47 | struct sdhci_pltfm_host *pltfm_host; | ||
48 | struct sdhci_sirf_priv *priv; | ||
49 | struct pinctrl *pinctrl; | ||
50 | int ret; | ||
51 | |||
52 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
53 | if (IS_ERR(pinctrl)) { | ||
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"); | ||
68 | return PTR_ERR(priv->clk); | ||
69 | } | ||
70 | |||
71 | if (pdev->dev.of_node) { | ||
72 | priv->gpio_cd = of_get_named_gpio(pdev->dev.of_node, | ||
73 | "cd-gpios", 0); | ||
74 | } else { | ||
75 | priv->gpio_cd = -EINVAL; | ||
76 | } | ||
77 | |||
78 | host = sdhci_pltfm_init(pdev, &sdhci_sirf_pdata); | ||
79 | if (IS_ERR(host)) { | ||
80 | ret = PTR_ERR(host); | ||
81 | goto err_sdhci_pltfm_init; | ||
82 | } | ||
83 | |||
84 | pltfm_host = sdhci_priv(host); | ||
85 | pltfm_host->priv = priv; | ||
86 | |||
87 | sdhci_get_of_property(pdev); | ||
88 | |||
89 | clk_prepare_enable(priv->clk); | ||
90 | |||
91 | ret = sdhci_add_host(host); | ||
92 | if (ret) | ||
93 | goto err_sdhci_add; | ||
94 | |||
95 | /* | ||
96 | * We must request the IRQ after sdhci_add_host(), as the tasklet only | ||
97 | * gets setup in sdhci_add_host() and we oops. | ||
98 | */ | ||
99 | if (gpio_is_valid(priv->gpio_cd)) { | ||
100 | ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd); | ||
101 | if (ret) { | ||
102 | dev_err(&pdev->dev, "card detect irq request failed: %d\n", | ||
103 | ret); | ||
104 | goto err_request_cd; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | return 0; | ||
109 | |||
110 | err_request_cd: | ||
111 | sdhci_remove_host(host, 0); | ||
112 | err_sdhci_add: | ||
113 | clk_disable_unprepare(priv->clk); | ||
114 | sdhci_pltfm_free(pdev); | ||
115 | err_sdhci_pltfm_init: | ||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | static int sdhci_sirf_remove(struct platform_device *pdev) | ||
120 | { | ||
121 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
122 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
123 | struct sdhci_sirf_priv *priv = pltfm_host->priv; | ||
124 | |||
125 | sdhci_pltfm_unregister(pdev); | ||
126 | |||
127 | if (gpio_is_valid(priv->gpio_cd)) | ||
128 | mmc_gpio_free_cd(host->mmc); | ||
129 | |||
130 | clk_disable_unprepare(priv->clk); | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | #ifdef CONFIG_PM_SLEEP | ||
135 | static int sdhci_sirf_suspend(struct device *dev) | ||
136 | { | ||
137 | struct sdhci_host *host = dev_get_drvdata(dev); | ||
138 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
139 | struct sdhci_sirf_priv *priv = pltfm_host->priv; | ||
140 | int ret; | ||
141 | |||
142 | ret = sdhci_suspend_host(host); | ||
143 | if (ret) | ||
144 | return ret; | ||
145 | |||
146 | clk_disable(priv->clk); | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int sdhci_sirf_resume(struct device *dev) | ||
152 | { | ||
153 | struct sdhci_host *host = dev_get_drvdata(dev); | ||
154 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
155 | struct sdhci_sirf_priv *priv = pltfm_host->priv; | ||
156 | int ret; | ||
157 | |||
158 | ret = clk_enable(priv->clk); | ||
159 | if (ret) { | ||
160 | dev_dbg(dev, "Resume: Error enabling clock\n"); | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | return sdhci_resume_host(host); | ||
165 | } | ||
166 | |||
167 | static SIMPLE_DEV_PM_OPS(sdhci_sirf_pm_ops, sdhci_sirf_suspend, sdhci_sirf_resume); | ||
168 | #endif | ||
169 | |||
170 | static const struct of_device_id sdhci_sirf_of_match[] = { | ||
171 | { .compatible = "sirf,prima2-sdhc" }, | ||
172 | { } | ||
173 | }; | ||
174 | MODULE_DEVICE_TABLE(of, sdhci_sirf_of_match); | ||
175 | |||
176 | static struct platform_driver sdhci_sirf_driver = { | ||
177 | .driver = { | ||
178 | .name = "sdhci-sirf", | ||
179 | .owner = THIS_MODULE, | ||
180 | .of_match_table = sdhci_sirf_of_match, | ||
181 | #ifdef CONFIG_PM_SLEEP | ||
182 | .pm = &sdhci_sirf_pm_ops, | ||
183 | #endif | ||
184 | }, | ||
185 | .probe = sdhci_sirf_probe, | ||
186 | .remove = sdhci_sirf_remove, | ||
187 | }; | ||
188 | |||
189 | module_platform_driver(sdhci_sirf_driver); | ||
190 | |||
191 | MODULE_DESCRIPTION("SDHCI driver for SiRFprimaII/SiRFmarco"); | ||
192 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
193 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index c6ece0bd03b3..7ae5b3ae7bad 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c | |||
@@ -36,7 +36,7 @@ struct spear_sdhci { | |||
36 | }; | 36 | }; |
37 | 37 | ||
38 | /* sdhci ops */ | 38 | /* sdhci ops */ |
39 | static struct sdhci_ops sdhci_pltfm_ops = { | 39 | static const struct sdhci_ops sdhci_pltfm_ops = { |
40 | /* Nothing to do for now. */ | 40 | /* Nothing to do for now. */ |
41 | }; | 41 | }; |
42 | 42 | ||
@@ -291,7 +291,7 @@ static int sdhci_remove(struct platform_device *pdev) | |||
291 | return 0; | 291 | return 0; |
292 | } | 292 | } |
293 | 293 | ||
294 | #ifdef CONFIG_PM | 294 | #ifdef CONFIG_PM_SLEEP |
295 | static int sdhci_suspend(struct device *dev) | 295 | static int sdhci_suspend(struct device *dev) |
296 | { | 296 | { |
297 | struct sdhci_host *host = dev_get_drvdata(dev); | 297 | struct sdhci_host *host = dev_get_drvdata(dev); |
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 08b06e9a3a21..e0dba74cff98 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/mmc/card.h> | 25 | #include <linux/mmc/card.h> |
26 | #include <linux/mmc/host.h> | 26 | #include <linux/mmc/host.h> |
27 | #include <linux/mmc/slot-gpio.h> | ||
27 | 28 | ||
28 | #include <asm/gpio.h> | 29 | #include <asm/gpio.h> |
29 | 30 | ||
@@ -38,16 +39,13 @@ | |||
38 | #define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2) | 39 | #define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2) |
39 | 40 | ||
40 | struct sdhci_tegra_soc_data { | 41 | struct sdhci_tegra_soc_data { |
41 | struct sdhci_pltfm_data *pdata; | 42 | const struct sdhci_pltfm_data *pdata; |
42 | u32 nvquirks; | 43 | u32 nvquirks; |
43 | }; | 44 | }; |
44 | 45 | ||
45 | struct sdhci_tegra { | 46 | struct sdhci_tegra { |
46 | const struct sdhci_tegra_soc_data *soc_data; | 47 | const struct sdhci_tegra_soc_data *soc_data; |
47 | int cd_gpio; | ||
48 | int wp_gpio; | ||
49 | int power_gpio; | 48 | int power_gpio; |
50 | int is_8bit; | ||
51 | }; | 49 | }; |
52 | 50 | ||
53 | static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg) | 51 | static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg) |
@@ -107,23 +105,9 @@ static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) | |||
107 | 105 | ||
108 | static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host) | 106 | static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host) |
109 | { | 107 | { |
110 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 108 | return mmc_gpio_get_ro(host->mmc); |
111 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | ||
112 | |||
113 | if (!gpio_is_valid(tegra_host->wp_gpio)) | ||
114 | return -1; | ||
115 | |||
116 | return gpio_get_value(tegra_host->wp_gpio); | ||
117 | } | 109 | } |
118 | 110 | ||
119 | static irqreturn_t carddetect_irq(int irq, void *data) | ||
120 | { | ||
121 | struct sdhci_host *sdhost = (struct sdhci_host *)data; | ||
122 | |||
123 | tasklet_schedule(&sdhost->card_tasklet); | ||
124 | return IRQ_HANDLED; | ||
125 | }; | ||
126 | |||
127 | static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask) | 111 | static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask) |
128 | { | 112 | { |
129 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 113 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
@@ -145,12 +129,11 @@ static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask) | |||
145 | 129 | ||
146 | static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width) | 130 | static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width) |
147 | { | 131 | { |
148 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
149 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | ||
150 | u32 ctrl; | 132 | u32 ctrl; |
151 | 133 | ||
152 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); | 134 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
153 | if (tegra_host->is_8bit && bus_width == MMC_BUS_WIDTH_8) { | 135 | if ((host->mmc->caps & MMC_CAP_8_BIT_DATA) && |
136 | (bus_width == MMC_BUS_WIDTH_8)) { | ||
154 | ctrl &= ~SDHCI_CTRL_4BITBUS; | 137 | ctrl &= ~SDHCI_CTRL_4BITBUS; |
155 | ctrl |= SDHCI_CTRL_8BITBUS; | 138 | ctrl |= SDHCI_CTRL_8BITBUS; |
156 | } else { | 139 | } else { |
@@ -164,7 +147,7 @@ static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width) | |||
164 | return 0; | 147 | return 0; |
165 | } | 148 | } |
166 | 149 | ||
167 | static struct sdhci_ops tegra_sdhci_ops = { | 150 | static const struct sdhci_ops tegra_sdhci_ops = { |
168 | .get_ro = tegra_sdhci_get_ro, | 151 | .get_ro = tegra_sdhci_get_ro, |
169 | .read_l = tegra_sdhci_readl, | 152 | .read_l = tegra_sdhci_readl, |
170 | .read_w = tegra_sdhci_readw, | 153 | .read_w = tegra_sdhci_readw, |
@@ -173,8 +156,7 @@ static struct sdhci_ops tegra_sdhci_ops = { | |||
173 | .platform_reset_exit = tegra_sdhci_reset_exit, | 156 | .platform_reset_exit = tegra_sdhci_reset_exit, |
174 | }; | 157 | }; |
175 | 158 | ||
176 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | 159 | static const struct sdhci_pltfm_data sdhci_tegra20_pdata = { |
177 | static struct sdhci_pltfm_data sdhci_tegra20_pdata = { | ||
178 | .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | | 160 | .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | |
179 | SDHCI_QUIRK_SINGLE_POWER_WRITE | | 161 | SDHCI_QUIRK_SINGLE_POWER_WRITE | |
180 | SDHCI_QUIRK_NO_HISPD_BIT | | 162 | SDHCI_QUIRK_NO_HISPD_BIT | |
@@ -187,10 +169,8 @@ static struct sdhci_tegra_soc_data soc_data_tegra20 = { | |||
187 | .nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 | | 169 | .nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 | |
188 | NVQUIRK_ENABLE_BLOCK_GAP_DET, | 170 | NVQUIRK_ENABLE_BLOCK_GAP_DET, |
189 | }; | 171 | }; |
190 | #endif | ||
191 | 172 | ||
192 | #ifdef CONFIG_ARCH_TEGRA_3x_SOC | 173 | static const struct sdhci_pltfm_data sdhci_tegra30_pdata = { |
193 | static struct sdhci_pltfm_data sdhci_tegra30_pdata = { | ||
194 | .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | | 174 | .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | |
195 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | | 175 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | |
196 | SDHCI_QUIRK_SINGLE_POWER_WRITE | | 176 | SDHCI_QUIRK_SINGLE_POWER_WRITE | |
@@ -203,32 +183,37 @@ static struct sdhci_tegra_soc_data soc_data_tegra30 = { | |||
203 | .pdata = &sdhci_tegra30_pdata, | 183 | .pdata = &sdhci_tegra30_pdata, |
204 | .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300, | 184 | .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300, |
205 | }; | 185 | }; |
206 | #endif | 186 | |
187 | static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { | ||
188 | .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | | ||
189 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | | ||
190 | SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
191 | SDHCI_QUIRK_NO_HISPD_BIT | | ||
192 | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, | ||
193 | .ops = &tegra_sdhci_ops, | ||
194 | }; | ||
195 | |||
196 | static struct sdhci_tegra_soc_data soc_data_tegra114 = { | ||
197 | .pdata = &sdhci_tegra114_pdata, | ||
198 | }; | ||
207 | 199 | ||
208 | static const struct of_device_id sdhci_tegra_dt_match[] = { | 200 | static const struct of_device_id sdhci_tegra_dt_match[] = { |
209 | #ifdef CONFIG_ARCH_TEGRA_3x_SOC | 201 | { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 }, |
210 | { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, | 202 | { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, |
211 | #endif | ||
212 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | ||
213 | { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, | 203 | { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, |
214 | #endif | ||
215 | {} | 204 | {} |
216 | }; | 205 | }; |
217 | MODULE_DEVICE_TABLE(of, sdhci_dt_ids); | 206 | MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); |
218 | 207 | ||
219 | static void sdhci_tegra_parse_dt(struct device *dev, | 208 | static void sdhci_tegra_parse_dt(struct device *dev) |
220 | struct sdhci_tegra *tegra_host) | ||
221 | { | 209 | { |
222 | struct device_node *np = dev->of_node; | 210 | struct device_node *np = dev->of_node; |
223 | u32 bus_width; | 211 | struct sdhci_host *host = dev_get_drvdata(dev); |
212 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
213 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | ||
224 | 214 | ||
225 | tegra_host->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); | ||
226 | tegra_host->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); | ||
227 | 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); |
228 | 216 | mmc_of_parse(host->mmc); | |
229 | if (of_property_read_u32(np, "bus-width", &bus_width) == 0 && | ||
230 | bus_width == 8) | ||
231 | tegra_host->is_8bit = 1; | ||
232 | } | 217 | } |
233 | 218 | ||
234 | static int sdhci_tegra_probe(struct platform_device *pdev) | 219 | static int sdhci_tegra_probe(struct platform_device *pdev) |
@@ -260,7 +245,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) | |||
260 | tegra_host->soc_data = soc_data; | 245 | tegra_host->soc_data = soc_data; |
261 | pltfm_host->priv = tegra_host; | 246 | pltfm_host->priv = tegra_host; |
262 | 247 | ||
263 | sdhci_tegra_parse_dt(&pdev->dev, tegra_host); | 248 | sdhci_tegra_parse_dt(&pdev->dev); |
264 | 249 | ||
265 | if (gpio_is_valid(tegra_host->power_gpio)) { | 250 | if (gpio_is_valid(tegra_host->power_gpio)) { |
266 | rc = gpio_request(tegra_host->power_gpio, "sdhci_power"); | 251 | rc = gpio_request(tegra_host->power_gpio, "sdhci_power"); |
@@ -272,37 +257,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev) | |||
272 | gpio_direction_output(tegra_host->power_gpio, 1); | 257 | gpio_direction_output(tegra_host->power_gpio, 1); |
273 | } | 258 | } |
274 | 259 | ||
275 | if (gpio_is_valid(tegra_host->cd_gpio)) { | ||
276 | rc = gpio_request(tegra_host->cd_gpio, "sdhci_cd"); | ||
277 | if (rc) { | ||
278 | dev_err(mmc_dev(host->mmc), | ||
279 | "failed to allocate cd gpio\n"); | ||
280 | goto err_cd_req; | ||
281 | } | ||
282 | gpio_direction_input(tegra_host->cd_gpio); | ||
283 | |||
284 | rc = request_irq(gpio_to_irq(tegra_host->cd_gpio), | ||
285 | carddetect_irq, | ||
286 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
287 | mmc_hostname(host->mmc), host); | ||
288 | |||
289 | if (rc) { | ||
290 | dev_err(mmc_dev(host->mmc), "request irq error\n"); | ||
291 | goto err_cd_irq_req; | ||
292 | } | ||
293 | |||
294 | } | ||
295 | |||
296 | if (gpio_is_valid(tegra_host->wp_gpio)) { | ||
297 | rc = gpio_request(tegra_host->wp_gpio, "sdhci_wp"); | ||
298 | if (rc) { | ||
299 | dev_err(mmc_dev(host->mmc), | ||
300 | "failed to allocate wp gpio\n"); | ||
301 | goto err_wp_req; | ||
302 | } | ||
303 | gpio_direction_input(tegra_host->wp_gpio); | ||
304 | } | ||
305 | |||
306 | clk = clk_get(mmc_dev(host->mmc), NULL); | 260 | clk = clk_get(mmc_dev(host->mmc), NULL); |
307 | if (IS_ERR(clk)) { | 261 | if (IS_ERR(clk)) { |
308 | dev_err(mmc_dev(host->mmc), "clk err\n"); | 262 | dev_err(mmc_dev(host->mmc), "clk err\n"); |
@@ -312,9 +266,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev) | |||
312 | clk_prepare_enable(clk); | 266 | clk_prepare_enable(clk); |
313 | pltfm_host->clk = clk; | 267 | pltfm_host->clk = clk; |
314 | 268 | ||
315 | if (tegra_host->is_8bit) | ||
316 | host->mmc->caps |= MMC_CAP_8_BIT_DATA; | ||
317 | |||
318 | rc = sdhci_add_host(host); | 269 | rc = sdhci_add_host(host); |
319 | if (rc) | 270 | if (rc) |
320 | goto err_add_host; | 271 | goto err_add_host; |
@@ -325,15 +276,6 @@ err_add_host: | |||
325 | clk_disable_unprepare(pltfm_host->clk); | 276 | clk_disable_unprepare(pltfm_host->clk); |
326 | clk_put(pltfm_host->clk); | 277 | clk_put(pltfm_host->clk); |
327 | err_clk_get: | 278 | err_clk_get: |
328 | if (gpio_is_valid(tegra_host->wp_gpio)) | ||
329 | gpio_free(tegra_host->wp_gpio); | ||
330 | err_wp_req: | ||
331 | if (gpio_is_valid(tegra_host->cd_gpio)) | ||
332 | free_irq(gpio_to_irq(tegra_host->cd_gpio), host); | ||
333 | err_cd_irq_req: | ||
334 | if (gpio_is_valid(tegra_host->cd_gpio)) | ||
335 | gpio_free(tegra_host->cd_gpio); | ||
336 | err_cd_req: | ||
337 | if (gpio_is_valid(tegra_host->power_gpio)) | 279 | if (gpio_is_valid(tegra_host->power_gpio)) |
338 | gpio_free(tegra_host->power_gpio); | 280 | gpio_free(tegra_host->power_gpio); |
339 | err_power_req: | 281 | err_power_req: |
@@ -351,14 +293,6 @@ static int sdhci_tegra_remove(struct platform_device *pdev) | |||
351 | 293 | ||
352 | sdhci_remove_host(host, dead); | 294 | sdhci_remove_host(host, dead); |
353 | 295 | ||
354 | if (gpio_is_valid(tegra_host->wp_gpio)) | ||
355 | gpio_free(tegra_host->wp_gpio); | ||
356 | |||
357 | if (gpio_is_valid(tegra_host->cd_gpio)) { | ||
358 | free_irq(gpio_to_irq(tegra_host->cd_gpio), host); | ||
359 | gpio_free(tegra_host->cd_gpio); | ||
360 | } | ||
361 | |||
362 | if (gpio_is_valid(tegra_host->power_gpio)) | 296 | if (gpio_is_valid(tegra_host->power_gpio)) |
363 | gpio_free(tegra_host->power_gpio); | 297 | gpio_free(tegra_host->power_gpio); |
364 | 298 | ||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 51bbba486f38..2ea429c27714 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -1581,6 +1581,37 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1581 | sdhci_runtime_pm_put(host); | 1581 | sdhci_runtime_pm_put(host); |
1582 | } | 1582 | } |
1583 | 1583 | ||
1584 | static int sdhci_do_get_cd(struct sdhci_host *host) | ||
1585 | { | ||
1586 | int gpio_cd = mmc_gpio_get_cd(host->mmc); | ||
1587 | |||
1588 | if (host->flags & SDHCI_DEVICE_DEAD) | ||
1589 | return 0; | ||
1590 | |||
1591 | /* If polling/nonremovable, assume that the card is always present. */ | ||
1592 | if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || | ||
1593 | (host->mmc->caps & MMC_CAP_NONREMOVABLE)) | ||
1594 | return 1; | ||
1595 | |||
1596 | /* Try slot gpio detect */ | ||
1597 | if (!IS_ERR_VALUE(gpio_cd)) | ||
1598 | return !!gpio_cd; | ||
1599 | |||
1600 | /* Host native card detect */ | ||
1601 | return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); | ||
1602 | } | ||
1603 | |||
1604 | static int sdhci_get_cd(struct mmc_host *mmc) | ||
1605 | { | ||
1606 | struct sdhci_host *host = mmc_priv(mmc); | ||
1607 | int ret; | ||
1608 | |||
1609 | sdhci_runtime_pm_get(host); | ||
1610 | ret = sdhci_do_get_cd(host); | ||
1611 | sdhci_runtime_pm_put(host); | ||
1612 | return ret; | ||
1613 | } | ||
1614 | |||
1584 | static int sdhci_check_ro(struct sdhci_host *host) | 1615 | static int sdhci_check_ro(struct sdhci_host *host) |
1585 | { | 1616 | { |
1586 | unsigned long flags; | 1617 | unsigned long flags; |
@@ -2038,6 +2069,7 @@ static void sdhci_card_event(struct mmc_host *mmc) | |||
2038 | static const struct mmc_host_ops sdhci_ops = { | 2069 | static const struct mmc_host_ops sdhci_ops = { |
2039 | .request = sdhci_request, | 2070 | .request = sdhci_request, |
2040 | .set_ios = sdhci_set_ios, | 2071 | .set_ios = sdhci_set_ios, |
2072 | .get_cd = sdhci_get_cd, | ||
2041 | .get_ro = sdhci_get_ro, | 2073 | .get_ro = sdhci_get_ro, |
2042 | .hw_reset = sdhci_hw_reset, | 2074 | .hw_reset = sdhci_hw_reset, |
2043 | .enable_sdio_irq = sdhci_enable_sdio_irq, | 2075 | .enable_sdio_irq = sdhci_enable_sdio_irq, |
@@ -2907,12 +2939,17 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2907 | host->vqmmc = NULL; | 2939 | host->vqmmc = NULL; |
2908 | } | 2940 | } |
2909 | } else { | 2941 | } else { |
2910 | regulator_enable(host->vqmmc); | 2942 | ret = regulator_enable(host->vqmmc); |
2911 | if (!regulator_is_supported_voltage(host->vqmmc, 1700000, | 2943 | if (!regulator_is_supported_voltage(host->vqmmc, 1700000, |
2912 | 1950000)) | 2944 | 1950000)) |
2913 | caps[1] &= ~(SDHCI_SUPPORT_SDR104 | | 2945 | caps[1] &= ~(SDHCI_SUPPORT_SDR104 | |
2914 | SDHCI_SUPPORT_SDR50 | | 2946 | SDHCI_SUPPORT_SDR50 | |
2915 | SDHCI_SUPPORT_DDR50); | 2947 | SDHCI_SUPPORT_DDR50); |
2948 | if (ret) { | ||
2949 | pr_warn("%s: Failed to enable vqmmc regulator: %d\n", | ||
2950 | mmc_hostname(mmc), ret); | ||
2951 | host->vqmmc = NULL; | ||
2952 | } | ||
2916 | } | 2953 | } |
2917 | 2954 | ||
2918 | if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) | 2955 | if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) |
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index c6d001509e5a..442f5766ffca 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c | |||
@@ -348,13 +348,11 @@ static void wmt_complete_data_request(struct wmt_mci_priv *priv) | |||
348 | 348 | ||
349 | static irqreturn_t wmt_mci_dma_isr(int irq_num, void *data) | 349 | static irqreturn_t wmt_mci_dma_isr(int irq_num, void *data) |
350 | { | 350 | { |
351 | struct mmc_host *mmc; | ||
352 | struct wmt_mci_priv *priv; | 351 | struct wmt_mci_priv *priv; |
353 | 352 | ||
354 | int status; | 353 | int status; |
355 | 354 | ||
356 | priv = (struct wmt_mci_priv *)data; | 355 | priv = (struct wmt_mci_priv *)data; |
357 | mmc = priv->mmc; | ||
358 | 356 | ||
359 | status = readl(priv->sdmmc_base + SDDMA_CCR) & 0x0F; | 357 | status = readl(priv->sdmmc_base + SDDMA_CCR) & 0x0F; |
360 | 358 | ||
@@ -925,7 +923,7 @@ static int wmt_mci_remove(struct platform_device *pdev) | |||
925 | clk_put(priv->clk_sdmmc); | 923 | clk_put(priv->clk_sdmmc); |
926 | 924 | ||
927 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 925 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
928 | release_mem_region(res->start, res->end - res->start + 1); | 926 | release_mem_region(res->start, resource_size(res)); |
929 | 927 | ||
930 | mmc_free_host(mmc); | 928 | mmc_free_host(mmc); |
931 | 929 | ||