diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-13 23:41:15 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-13 23:41:15 -0500 |
commit | 4b8be38cf782f8ebebc089083fa0572ade79d7ca (patch) | |
tree | 2f88a0a5c1c0be9121c31b5a2775ae2f979cfa66 /drivers/mmc/host | |
parent | 5df1b274cd2f0304339c7f5586fa16cce0fdfce2 (diff) | |
parent | 0db13fc2abbb0b1a8d8efee20dfbd7f3c5d54022 (diff) |
Merge tag 'mmc-merge-for-3.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
MMC highlights for 3.3:
Core:
* Support for the HS200 high-speed eMMC mode.
* Support SDIO 3.0 Ultra High Speed cards.
* Kill pending block requests immediately if card is removed.
* Enable the eMMC feature for locking boot partitions read-only
until next power on, exposed via sysfs.
Drivers:
* Runtime PM support for Intel Medfield SDIO.
* Suspend/resume support for sdhci-spear.
* sh-mmcif now processes requests asynchronously.
* tag 'mmc-merge-for-3.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (58 commits)
mmc: fix a deadlock between system suspend and MMC block IO
mmc: sdhci: restore the enabled dma when do reset all
mmc: dw_mmc: miscaculated the fifo-depth with wrong bit operation
mmc: host: Adds support for eMMC 4.5 HS200 mode
mmc: core: HS200 mode support for eMMC 4.5
mmc: dw_mmc: fixed wrong bit operation for SDMMC_GET_FCNT()
mmc: core: Separate the timeout value for cache-ctrl
mmc: sdhci-spear: Fix compilation error
mmc: sdhci: Deal with failure case in sdhci_suspend_host
mmc: dw_mmc: Clear the DDR mode for non-DDR
mmc: sd: Fix SDR12 timing regression
mmc: sdhci: Fix tuning timer incorrect setting when suspending host
mmc: core: Add option to prevent eMMC sleep command
mmc: omap_hsmmc: use threaded irq handler for card-detect.
mmc: sdhci-pci: enable runtime PM for Medfield SDIO
mmc: sdhci: Always pass clock request value zero to set_clock host op
mmc: sdhci-pci: remove SDHCI_QUIRK2_OWN_CARD_DETECTION
mmc: sdhci-pci: get gpio numbers from platform data
mmc: sdhci-pci: add platform data
mmc: sdhci: prevent card detection activity for non-removable cards
...
Diffstat (limited to 'drivers/mmc/host')
36 files changed, 839 insertions, 703 deletions
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index b4b83f302e32..745f8fce2519 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_MMC_MXC) += mxcmmc.o | |||
9 | obj-$(CONFIG_MMC_MXS) += mxs-mmc.o | 9 | obj-$(CONFIG_MMC_MXS) += mxs-mmc.o |
10 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o | 10 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o |
11 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o | 11 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o |
12 | obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o | ||
12 | obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o | 13 | obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o |
13 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o | 14 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o |
14 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o | 15 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o |
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index f437c3e6f3aa..947faa5d2ce4 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c | |||
@@ -236,7 +236,7 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data | |||
236 | 236 | ||
237 | sg = &data->sg[i]; | 237 | sg = &data->sg[i]; |
238 | 238 | ||
239 | sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; | 239 | sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset; |
240 | amount = min(size, sg->length); | 240 | amount = min(size, sg->length); |
241 | size -= amount; | 241 | size -= amount; |
242 | 242 | ||
@@ -252,7 +252,7 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data | |||
252 | dmabuf = (unsigned *)tmpv; | 252 | dmabuf = (unsigned *)tmpv; |
253 | } | 253 | } |
254 | 254 | ||
255 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); | 255 | kunmap_atomic(sgbuffer); |
256 | 256 | ||
257 | if (size == 0) | 257 | if (size == 0) |
258 | break; | 258 | break; |
@@ -302,7 +302,7 @@ static void at91_mci_post_dma_read(struct at91mci_host *host) | |||
302 | 302 | ||
303 | sg = &data->sg[i]; | 303 | sg = &data->sg[i]; |
304 | 304 | ||
305 | sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; | 305 | sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset; |
306 | amount = min(size, sg->length); | 306 | amount = min(size, sg->length); |
307 | size -= amount; | 307 | size -= amount; |
308 | 308 | ||
@@ -318,7 +318,7 @@ static void at91_mci_post_dma_read(struct at91mci_host *host) | |||
318 | } | 318 | } |
319 | 319 | ||
320 | flush_kernel_dcache_page(sg_page(sg)); | 320 | flush_kernel_dcache_page(sg_page(sg)); |
321 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); | 321 | kunmap_atomic(sgbuffer); |
322 | data->bytes_xfered += amount; | 322 | data->bytes_xfered += amount; |
323 | if (size == 0) | 323 | if (size == 0) |
324 | break; | 324 | break; |
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index 0371bf502249..03666174ca48 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c | |||
@@ -627,17 +627,7 @@ static struct platform_driver sdh_driver = { | |||
627 | }, | 627 | }, |
628 | }; | 628 | }; |
629 | 629 | ||
630 | static int __init sdh_init(void) | 630 | module_platform_driver(sdh_driver); |
631 | { | ||
632 | return platform_driver_register(&sdh_driver); | ||
633 | } | ||
634 | module_init(sdh_init); | ||
635 | |||
636 | static void __exit sdh_exit(void) | ||
637 | { | ||
638 | platform_driver_unregister(&sdh_driver); | ||
639 | } | ||
640 | module_exit(sdh_exit); | ||
641 | 631 | ||
642 | MODULE_DESCRIPTION("Blackfin Secure Digital Host Driver"); | 632 | MODULE_DESCRIPTION("Blackfin Secure Digital Host Driver"); |
643 | MODULE_AUTHOR("Cliff Cai, Roy Huang"); | 633 | MODULE_AUTHOR("Cliff Cai, Roy Huang"); |
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c index ce2a47b71dd6..83693fd7c6b3 100644 --- a/drivers/mmc/host/cb710-mmc.c +++ b/drivers/mmc/host/cb710-mmc.c | |||
@@ -780,18 +780,7 @@ static struct platform_driver cb710_mmc_driver = { | |||
780 | #endif | 780 | #endif |
781 | }; | 781 | }; |
782 | 782 | ||
783 | static int __init cb710_mmc_init_module(void) | 783 | module_platform_driver(cb710_mmc_driver); |
784 | { | ||
785 | return platform_driver_register(&cb710_mmc_driver); | ||
786 | } | ||
787 | |||
788 | static void __exit cb710_mmc_cleanup_module(void) | ||
789 | { | ||
790 | platform_driver_unregister(&cb710_mmc_driver); | ||
791 | } | ||
792 | |||
793 | module_init(cb710_mmc_init_module); | ||
794 | module_exit(cb710_mmc_cleanup_module); | ||
795 | 784 | ||
796 | MODULE_AUTHOR("Michał Mirosław <mirq-linux@rere.qmqm.pl>"); | 785 | MODULE_AUTHOR("Michał Mirosław <mirq-linux@rere.qmqm.pl>"); |
797 | MODULE_DESCRIPTION("ENE CB710 memory card reader driver - MMC/SD part"); | 786 | MODULE_DESCRIPTION("ENE CB710 memory card reader driver - MMC/SD part"); |
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 3aaeb0841914..0e342793ff14 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -588,11 +588,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) | |||
588 | mci_writel(host, CTYPE, (slot->ctype << slot->id)); | 588 | mci_writel(host, CTYPE, (slot->ctype << slot->id)); |
589 | } | 589 | } |
590 | 590 | ||
591 | static void dw_mci_start_request(struct dw_mci *host, | 591 | static void __dw_mci_start_request(struct dw_mci *host, |
592 | struct dw_mci_slot *slot) | 592 | struct dw_mci_slot *slot, |
593 | struct mmc_command *cmd) | ||
593 | { | 594 | { |
594 | struct mmc_request *mrq; | 595 | struct mmc_request *mrq; |
595 | struct mmc_command *cmd; | ||
596 | struct mmc_data *data; | 596 | struct mmc_data *data; |
597 | u32 cmdflags; | 597 | u32 cmdflags; |
598 | 598 | ||
@@ -610,14 +610,13 @@ static void dw_mci_start_request(struct dw_mci *host, | |||
610 | host->completed_events = 0; | 610 | host->completed_events = 0; |
611 | host->data_status = 0; | 611 | host->data_status = 0; |
612 | 612 | ||
613 | data = mrq->data; | 613 | data = cmd->data; |
614 | if (data) { | 614 | if (data) { |
615 | dw_mci_set_timeout(host); | 615 | dw_mci_set_timeout(host); |
616 | mci_writel(host, BYTCNT, data->blksz*data->blocks); | 616 | mci_writel(host, BYTCNT, data->blksz*data->blocks); |
617 | mci_writel(host, BLKSIZ, data->blksz); | 617 | mci_writel(host, BLKSIZ, data->blksz); |
618 | } | 618 | } |
619 | 619 | ||
620 | cmd = mrq->cmd; | ||
621 | cmdflags = dw_mci_prepare_command(slot->mmc, cmd); | 620 | cmdflags = dw_mci_prepare_command(slot->mmc, cmd); |
622 | 621 | ||
623 | /* this is the first command, send the initialization clock */ | 622 | /* this is the first command, send the initialization clock */ |
@@ -635,6 +634,16 @@ static void dw_mci_start_request(struct dw_mci *host, | |||
635 | host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); | 634 | host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); |
636 | } | 635 | } |
637 | 636 | ||
637 | static void dw_mci_start_request(struct dw_mci *host, | ||
638 | struct dw_mci_slot *slot) | ||
639 | { | ||
640 | struct mmc_request *mrq = slot->mrq; | ||
641 | struct mmc_command *cmd; | ||
642 | |||
643 | cmd = mrq->sbc ? mrq->sbc : mrq->cmd; | ||
644 | __dw_mci_start_request(host, slot, cmd); | ||
645 | } | ||
646 | |||
638 | /* must be called with host->lock held */ | 647 | /* must be called with host->lock held */ |
639 | static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot, | 648 | static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot, |
640 | struct mmc_request *mrq) | 649 | struct mmc_request *mrq) |
@@ -698,12 +707,15 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
698 | break; | 707 | break; |
699 | } | 708 | } |
700 | 709 | ||
710 | regs = mci_readl(slot->host, UHS_REG); | ||
711 | |||
701 | /* DDR mode set */ | 712 | /* DDR mode set */ |
702 | if (ios->timing == MMC_TIMING_UHS_DDR50) { | 713 | if (ios->timing == MMC_TIMING_UHS_DDR50) |
703 | regs = mci_readl(slot->host, UHS_REG); | ||
704 | regs |= (0x1 << slot->id) << 16; | 714 | regs |= (0x1 << slot->id) << 16; |
705 | mci_writel(slot->host, UHS_REG, regs); | 715 | else |
706 | } | 716 | regs &= ~(0x1 << slot->id) << 16; |
717 | |||
718 | mci_writel(slot->host, UHS_REG, regs); | ||
707 | 719 | ||
708 | if (ios->clock) { | 720 | if (ios->clock) { |
709 | /* | 721 | /* |
@@ -889,7 +901,14 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
889 | cmd = host->cmd; | 901 | cmd = host->cmd; |
890 | host->cmd = NULL; | 902 | host->cmd = NULL; |
891 | set_bit(EVENT_CMD_COMPLETE, &host->completed_events); | 903 | set_bit(EVENT_CMD_COMPLETE, &host->completed_events); |
892 | dw_mci_command_complete(host, host->mrq->cmd); | 904 | dw_mci_command_complete(host, cmd); |
905 | if (cmd == host->mrq->sbc && !cmd->error) { | ||
906 | prev_state = state = STATE_SENDING_CMD; | ||
907 | __dw_mci_start_request(host, host->cur_slot, | ||
908 | host->mrq->cmd); | ||
909 | goto unlock; | ||
910 | } | ||
911 | |||
893 | if (!host->mrq->data || cmd->error) { | 912 | if (!host->mrq->data || cmd->error) { |
894 | dw_mci_request_end(host, host->mrq); | 913 | dw_mci_request_end(host, host->mrq); |
895 | goto unlock; | 914 | goto unlock; |
@@ -967,6 +986,12 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
967 | goto unlock; | 986 | goto unlock; |
968 | } | 987 | } |
969 | 988 | ||
989 | if (host->mrq->sbc && !data->error) { | ||
990 | data->stop->error = 0; | ||
991 | dw_mci_request_end(host, host->mrq); | ||
992 | goto unlock; | ||
993 | } | ||
994 | |||
970 | prev_state = state = STATE_SENDING_STOP; | 995 | prev_state = state = STATE_SENDING_STOP; |
971 | if (!data->error) | 996 | if (!data->error) |
972 | send_stop_cmd(host, data); | 997 | send_stop_cmd(host, data); |
@@ -1678,8 +1703,9 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1678 | 1703 | ||
1679 | if (host->pdata->caps) | 1704 | if (host->pdata->caps) |
1680 | mmc->caps = host->pdata->caps; | 1705 | mmc->caps = host->pdata->caps; |
1681 | else | 1706 | |
1682 | mmc->caps = 0; | 1707 | if (host->pdata->caps2) |
1708 | mmc->caps2 = host->pdata->caps2; | ||
1683 | 1709 | ||
1684 | if (host->pdata->get_bus_wd) | 1710 | if (host->pdata->get_bus_wd) |
1685 | if (host->pdata->get_bus_wd(slot->id) >= 4) | 1711 | if (host->pdata->get_bus_wd(slot->id) >= 4) |
@@ -1923,7 +1949,7 @@ static int dw_mci_probe(struct platform_device *pdev) | |||
1923 | * should put it in the platform data. | 1949 | * should put it in the platform data. |
1924 | */ | 1950 | */ |
1925 | fifo_size = mci_readl(host, FIFOTH); | 1951 | fifo_size = mci_readl(host, FIFOTH); |
1926 | fifo_size = 1 + ((fifo_size >> 16) & 0x7ff); | 1952 | fifo_size = 1 + ((fifo_size >> 16) & 0xfff); |
1927 | } else { | 1953 | } else { |
1928 | fifo_size = host->pdata->fifo_depth; | 1954 | fifo_size = host->pdata->fifo_depth; |
1929 | } | 1955 | } |
@@ -2062,14 +2088,14 @@ static int __exit dw_mci_remove(struct platform_device *pdev) | |||
2062 | return 0; | 2088 | return 0; |
2063 | } | 2089 | } |
2064 | 2090 | ||
2065 | #ifdef CONFIG_PM | 2091 | #ifdef CONFIG_PM_SLEEP |
2066 | /* | 2092 | /* |
2067 | * TODO: we should probably disable the clock to the card in the suspend path. | 2093 | * TODO: we should probably disable the clock to the card in the suspend path. |
2068 | */ | 2094 | */ |
2069 | static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg) | 2095 | static int dw_mci_suspend(struct device *dev) |
2070 | { | 2096 | { |
2071 | int i, ret; | 2097 | int i, ret; |
2072 | struct dw_mci *host = platform_get_drvdata(pdev); | 2098 | struct dw_mci *host = dev_get_drvdata(dev); |
2073 | 2099 | ||
2074 | for (i = 0; i < host->num_slots; i++) { | 2100 | for (i = 0; i < host->num_slots; i++) { |
2075 | struct dw_mci_slot *slot = host->slot[i]; | 2101 | struct dw_mci_slot *slot = host->slot[i]; |
@@ -2092,10 +2118,10 @@ static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
2092 | return 0; | 2118 | return 0; |
2093 | } | 2119 | } |
2094 | 2120 | ||
2095 | static int dw_mci_resume(struct platform_device *pdev) | 2121 | static int dw_mci_resume(struct device *dev) |
2096 | { | 2122 | { |
2097 | int i, ret; | 2123 | int i, ret; |
2098 | struct dw_mci *host = platform_get_drvdata(pdev); | 2124 | struct dw_mci *host = dev_get_drvdata(dev); |
2099 | 2125 | ||
2100 | if (host->vmmc) | 2126 | if (host->vmmc) |
2101 | regulator_enable(host->vmmc); | 2127 | regulator_enable(host->vmmc); |
@@ -2103,7 +2129,7 @@ static int dw_mci_resume(struct platform_device *pdev) | |||
2103 | if (host->dma_ops->init) | 2129 | if (host->dma_ops->init) |
2104 | host->dma_ops->init(host); | 2130 | host->dma_ops->init(host); |
2105 | 2131 | ||
2106 | if (!mci_wait_reset(&pdev->dev, host)) { | 2132 | if (!mci_wait_reset(dev, host)) { |
2107 | ret = -ENODEV; | 2133 | ret = -ENODEV; |
2108 | return ret; | 2134 | return ret; |
2109 | } | 2135 | } |
@@ -2131,14 +2157,15 @@ static int dw_mci_resume(struct platform_device *pdev) | |||
2131 | #else | 2157 | #else |
2132 | #define dw_mci_suspend NULL | 2158 | #define dw_mci_suspend NULL |
2133 | #define dw_mci_resume NULL | 2159 | #define dw_mci_resume NULL |
2134 | #endif /* CONFIG_PM */ | 2160 | #endif /* CONFIG_PM_SLEEP */ |
2161 | |||
2162 | static SIMPLE_DEV_PM_OPS(dw_mci_pmops, dw_mci_suspend, dw_mci_resume); | ||
2135 | 2163 | ||
2136 | static struct platform_driver dw_mci_driver = { | 2164 | static struct platform_driver dw_mci_driver = { |
2137 | .remove = __exit_p(dw_mci_remove), | 2165 | .remove = __exit_p(dw_mci_remove), |
2138 | .suspend = dw_mci_suspend, | ||
2139 | .resume = dw_mci_resume, | ||
2140 | .driver = { | 2166 | .driver = { |
2141 | .name = "dw_mmc", | 2167 | .name = "dw_mmc", |
2168 | .pm = &dw_mci_pmops, | ||
2142 | }, | 2169 | }, |
2143 | }; | 2170 | }; |
2144 | 2171 | ||
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 72c071f6e001..df392a1143f2 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h | |||
@@ -126,7 +126,7 @@ | |||
126 | #define SDMMC_CMD_RESP_EXP BIT(6) | 126 | #define SDMMC_CMD_RESP_EXP BIT(6) |
127 | #define SDMMC_CMD_INDX(n) ((n) & 0x1F) | 127 | #define SDMMC_CMD_INDX(n) ((n) & 0x1F) |
128 | /* Status register defines */ | 128 | /* Status register defines */ |
129 | #define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FF) | 129 | #define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF) |
130 | /* Internal DMAC interrupt defines */ | 130 | /* Internal DMAC interrupt defines */ |
131 | #define SDMMC_IDMAC_INT_AI BIT(9) | 131 | #define SDMMC_IDMAC_INT_AI BIT(9) |
132 | #define SDMMC_IDMAC_INT_NI BIT(8) | 132 | #define SDMMC_IDMAC_INT_NI BIT(8) |
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 74218ad677e4..c8852a8128a9 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c | |||
@@ -1012,17 +1012,7 @@ static struct platform_driver jz4740_mmc_driver = { | |||
1012 | }, | 1012 | }, |
1013 | }; | 1013 | }; |
1014 | 1014 | ||
1015 | static int __init jz4740_mmc_init(void) | 1015 | module_platform_driver(jz4740_mmc_driver); |
1016 | { | ||
1017 | return platform_driver_register(&jz4740_mmc_driver); | ||
1018 | } | ||
1019 | module_init(jz4740_mmc_init); | ||
1020 | |||
1021 | static void __exit jz4740_mmc_exit(void) | ||
1022 | { | ||
1023 | platform_driver_unregister(&jz4740_mmc_driver); | ||
1024 | } | ||
1025 | module_exit(jz4740_mmc_exit); | ||
1026 | 1016 | ||
1027 | MODULE_DESCRIPTION("JZ4740 SD/MMC controller driver"); | 1017 | MODULE_DESCRIPTION("JZ4740 SD/MMC controller driver"); |
1028 | MODULE_LICENSE("GPL"); | 1018 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 92946b84e9fa..273306c68d58 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
@@ -1525,7 +1525,6 @@ static struct of_device_id mmc_spi_of_match_table[] __devinitdata = { | |||
1525 | static struct spi_driver mmc_spi_driver = { | 1525 | static struct spi_driver mmc_spi_driver = { |
1526 | .driver = { | 1526 | .driver = { |
1527 | .name = "mmc_spi", | 1527 | .name = "mmc_spi", |
1528 | .bus = &spi_bus_type, | ||
1529 | .owner = THIS_MODULE, | 1528 | .owner = THIS_MODULE, |
1530 | .of_match_table = mmc_spi_of_match_table, | 1529 | .of_match_table = mmc_spi_of_match_table, |
1531 | }, | 1530 | }, |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index fa8dd2fda4b2..ece03b491c7d 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -1245,6 +1245,7 @@ static int __devinit mmci_probe(struct amba_device *dev, | |||
1245 | if (host->vcc == NULL) | 1245 | if (host->vcc == NULL) |
1246 | mmc->ocr_avail = plat->ocr_mask; | 1246 | mmc->ocr_avail = plat->ocr_mask; |
1247 | mmc->caps = plat->capabilities; | 1247 | mmc->caps = plat->capabilities; |
1248 | mmc->caps2 = plat->capabilities2; | ||
1248 | 1249 | ||
1249 | /* | 1250 | /* |
1250 | * We can do SGIO | 1251 | * We can do SGIO |
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index 80d8eb143b48..1d14cda95e56 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c | |||
@@ -689,8 +689,8 @@ msmsdcc_pio_irq(int irq, void *dev_id) | |||
689 | 689 | ||
690 | /* Map the current scatter buffer */ | 690 | /* Map the current scatter buffer */ |
691 | local_irq_save(flags); | 691 | local_irq_save(flags); |
692 | buffer = kmap_atomic(sg_page(host->pio.sg), | 692 | buffer = kmap_atomic(sg_page(host->pio.sg)) |
693 | KM_BIO_SRC_IRQ) + host->pio.sg->offset; | 693 | + host->pio.sg->offset; |
694 | buffer += host->pio.sg_off; | 694 | buffer += host->pio.sg_off; |
695 | remain = host->pio.sg->length - host->pio.sg_off; | 695 | remain = host->pio.sg->length - host->pio.sg_off; |
696 | len = 0; | 696 | len = 0; |
@@ -700,7 +700,7 @@ msmsdcc_pio_irq(int irq, void *dev_id) | |||
700 | len = msmsdcc_pio_write(host, buffer, remain, status); | 700 | len = msmsdcc_pio_write(host, buffer, remain, status); |
701 | 701 | ||
702 | /* Unmap the buffer */ | 702 | /* Unmap the buffer */ |
703 | kunmap_atomic(buffer, KM_BIO_SRC_IRQ); | 703 | kunmap_atomic(buffer); |
704 | local_irq_restore(flags); | 704 | local_irq_restore(flags); |
705 | 705 | ||
706 | host->pio.sg_off += len; | 706 | host->pio.sg_off += len; |
@@ -1480,18 +1480,7 @@ static struct platform_driver msmsdcc_driver = { | |||
1480 | }, | 1480 | }, |
1481 | }; | 1481 | }; |
1482 | 1482 | ||
1483 | static int __init msmsdcc_init(void) | 1483 | module_platform_driver(msmsdcc_driver); |
1484 | { | ||
1485 | return platform_driver_register(&msmsdcc_driver); | ||
1486 | } | ||
1487 | |||
1488 | static void __exit msmsdcc_exit(void) | ||
1489 | { | ||
1490 | platform_driver_unregister(&msmsdcc_driver); | ||
1491 | } | ||
1492 | |||
1493 | module_init(msmsdcc_init); | ||
1494 | module_exit(msmsdcc_exit); | ||
1495 | 1484 | ||
1496 | MODULE_DESCRIPTION("Qualcomm MSM 7X00A Multimedia Card Interface driver"); | 1485 | MODULE_DESCRIPTION("Qualcomm MSM 7X00A Multimedia Card Interface driver"); |
1497 | MODULE_LICENSE("GPL"); | 1486 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 8e0fbe994047..7088b40f9579 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -1047,18 +1047,7 @@ static struct platform_driver mxcmci_driver = { | |||
1047 | } | 1047 | } |
1048 | }; | 1048 | }; |
1049 | 1049 | ||
1050 | static int __init mxcmci_init(void) | 1050 | module_platform_driver(mxcmci_driver); |
1051 | { | ||
1052 | return platform_driver_register(&mxcmci_driver); | ||
1053 | } | ||
1054 | |||
1055 | static void __exit mxcmci_exit(void) | ||
1056 | { | ||
1057 | platform_driver_unregister(&mxcmci_driver); | ||
1058 | } | ||
1059 | |||
1060 | module_init(mxcmci_init); | ||
1061 | module_exit(mxcmci_exit); | ||
1062 | 1051 | ||
1063 | MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); | 1052 | MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); |
1064 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); | 1053 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); |
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 973011f9a298..4e2e019dd5c9 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c | |||
@@ -855,18 +855,7 @@ static struct platform_driver mxs_mmc_driver = { | |||
855 | }, | 855 | }, |
856 | }; | 856 | }; |
857 | 857 | ||
858 | static int __init mxs_mmc_init(void) | 858 | module_platform_driver(mxs_mmc_driver); |
859 | { | ||
860 | return platform_driver_register(&mxs_mmc_driver); | ||
861 | } | ||
862 | |||
863 | static void __exit mxs_mmc_exit(void) | ||
864 | { | ||
865 | platform_driver_unregister(&mxs_mmc_driver); | ||
866 | } | ||
867 | |||
868 | module_init(mxs_mmc_init); | ||
869 | module_exit(mxs_mmc_exit); | ||
870 | 859 | ||
871 | MODULE_DESCRIPTION("FREESCALE MXS MMC peripheral"); | 860 | MODULE_DESCRIPTION("FREESCALE MXS MMC peripheral"); |
872 | MODULE_AUTHOR("Freescale Semiconductor"); | 861 | MODULE_AUTHOR("Freescale Semiconductor"); |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index d1fb561e089d..fd0c661bbad3 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/workqueue.h> | ||
28 | #include <linux/timer.h> | 27 | #include <linux/timer.h> |
29 | #include <linux/clk.h> | 28 | #include <linux/clk.h> |
30 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
@@ -120,7 +119,6 @@ | |||
120 | 119 | ||
121 | #define MMC_AUTOSUSPEND_DELAY 100 | 120 | #define MMC_AUTOSUSPEND_DELAY 100 |
122 | #define MMC_TIMEOUT_MS 20 | 121 | #define MMC_TIMEOUT_MS 20 |
123 | #define OMAP_MMC_MASTER_CLOCK 96000000 | ||
124 | #define OMAP_MMC_MIN_CLOCK 400000 | 122 | #define OMAP_MMC_MIN_CLOCK 400000 |
125 | #define OMAP_MMC_MAX_CLOCK 52000000 | 123 | #define OMAP_MMC_MAX_CLOCK 52000000 |
126 | #define DRIVER_NAME "omap_hsmmc" | 124 | #define DRIVER_NAME "omap_hsmmc" |
@@ -163,7 +161,6 @@ struct omap_hsmmc_host { | |||
163 | */ | 161 | */ |
164 | struct regulator *vcc; | 162 | struct regulator *vcc; |
165 | struct regulator *vcc_aux; | 163 | struct regulator *vcc_aux; |
166 | struct work_struct mmc_carddetect_work; | ||
167 | void __iomem *base; | 164 | void __iomem *base; |
168 | resource_size_t mapbase; | 165 | resource_size_t mapbase; |
169 | spinlock_t irq_lock; /* Prevent races with irq handler */ | 166 | spinlock_t irq_lock; /* Prevent races with irq handler */ |
@@ -598,12 +595,12 @@ static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host) | |||
598 | } | 595 | } |
599 | 596 | ||
600 | /* Calculate divisor for the given clock frequency */ | 597 | /* Calculate divisor for the given clock frequency */ |
601 | static u16 calc_divisor(struct mmc_ios *ios) | 598 | static u16 calc_divisor(struct omap_hsmmc_host *host, struct mmc_ios *ios) |
602 | { | 599 | { |
603 | u16 dsor = 0; | 600 | u16 dsor = 0; |
604 | 601 | ||
605 | if (ios->clock) { | 602 | if (ios->clock) { |
606 | dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, ios->clock); | 603 | dsor = DIV_ROUND_UP(clk_get_rate(host->fclk), ios->clock); |
607 | if (dsor > 250) | 604 | if (dsor > 250) |
608 | dsor = 250; | 605 | dsor = 250; |
609 | } | 606 | } |
@@ -623,7 +620,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host) | |||
623 | 620 | ||
624 | regval = OMAP_HSMMC_READ(host->base, SYSCTL); | 621 | regval = OMAP_HSMMC_READ(host->base, SYSCTL); |
625 | regval = regval & ~(CLKD_MASK | DTO_MASK); | 622 | regval = regval & ~(CLKD_MASK | DTO_MASK); |
626 | regval = regval | (calc_divisor(ios) << 6) | (DTO << 16); | 623 | regval = regval | (calc_divisor(host, ios) << 6) | (DTO << 16); |
627 | OMAP_HSMMC_WRITE(host->base, SYSCTL, regval); | 624 | OMAP_HSMMC_WRITE(host->base, SYSCTL, regval); |
628 | OMAP_HSMMC_WRITE(host->base, SYSCTL, | 625 | OMAP_HSMMC_WRITE(host->base, SYSCTL, |
629 | OMAP_HSMMC_READ(host->base, SYSCTL) | ICE); | 626 | OMAP_HSMMC_READ(host->base, SYSCTL) | ICE); |
@@ -1280,17 +1277,16 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) | |||
1280 | } | 1277 | } |
1281 | 1278 | ||
1282 | /* | 1279 | /* |
1283 | * Work Item to notify the core about card insertion/removal | 1280 | * irq handler to notify the core about card insertion/removal |
1284 | */ | 1281 | */ |
1285 | static void omap_hsmmc_detect(struct work_struct *work) | 1282 | static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) |
1286 | { | 1283 | { |
1287 | struct omap_hsmmc_host *host = | 1284 | struct omap_hsmmc_host *host = dev_id; |
1288 | container_of(work, struct omap_hsmmc_host, mmc_carddetect_work); | ||
1289 | struct omap_mmc_slot_data *slot = &mmc_slot(host); | 1285 | struct omap_mmc_slot_data *slot = &mmc_slot(host); |
1290 | int carddetect; | 1286 | int carddetect; |
1291 | 1287 | ||
1292 | if (host->suspended) | 1288 | if (host->suspended) |
1293 | return; | 1289 | return IRQ_HANDLED; |
1294 | 1290 | ||
1295 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); | 1291 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); |
1296 | 1292 | ||
@@ -1305,19 +1301,6 @@ static void omap_hsmmc_detect(struct work_struct *work) | |||
1305 | mmc_detect_change(host->mmc, (HZ * 200) / 1000); | 1301 | mmc_detect_change(host->mmc, (HZ * 200) / 1000); |
1306 | else | 1302 | else |
1307 | mmc_detect_change(host->mmc, (HZ * 50) / 1000); | 1303 | mmc_detect_change(host->mmc, (HZ * 50) / 1000); |
1308 | } | ||
1309 | |||
1310 | /* | ||
1311 | * ISR for handling card insertion and removal | ||
1312 | */ | ||
1313 | static irqreturn_t omap_hsmmc_cd_handler(int irq, void *dev_id) | ||
1314 | { | ||
1315 | struct omap_hsmmc_host *host = (struct omap_hsmmc_host *)dev_id; | ||
1316 | |||
1317 | if (host->suspended) | ||
1318 | return IRQ_HANDLED; | ||
1319 | schedule_work(&host->mmc_carddetect_work); | ||
1320 | |||
1321 | return IRQ_HANDLED; | 1304 | return IRQ_HANDLED; |
1322 | } | 1305 | } |
1323 | 1306 | ||
@@ -1919,7 +1902,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
1919 | host->next_data.cookie = 1; | 1902 | host->next_data.cookie = 1; |
1920 | 1903 | ||
1921 | platform_set_drvdata(pdev, host); | 1904 | platform_set_drvdata(pdev, host); |
1922 | INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect); | ||
1923 | 1905 | ||
1924 | mmc->ops = &omap_hsmmc_ops; | 1906 | mmc->ops = &omap_hsmmc_ops; |
1925 | 1907 | ||
@@ -2049,10 +2031,11 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2049 | 2031 | ||
2050 | /* Request IRQ for card detect */ | 2032 | /* Request IRQ for card detect */ |
2051 | if ((mmc_slot(host).card_detect_irq)) { | 2033 | if ((mmc_slot(host).card_detect_irq)) { |
2052 | ret = request_irq(mmc_slot(host).card_detect_irq, | 2034 | ret = request_threaded_irq(mmc_slot(host).card_detect_irq, |
2053 | omap_hsmmc_cd_handler, | 2035 | NULL, |
2054 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | 2036 | omap_hsmmc_detect, |
2055 | mmc_hostname(mmc), host); | 2037 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
2038 | mmc_hostname(mmc), host); | ||
2056 | if (ret) { | 2039 | if (ret) { |
2057 | dev_dbg(mmc_dev(host->mmc), | 2040 | dev_dbg(mmc_dev(host->mmc), |
2058 | "Unable to grab MMC CD IRQ\n"); | 2041 | "Unable to grab MMC CD IRQ\n"); |
@@ -2131,7 +2114,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
2131 | free_irq(host->irq, host); | 2114 | free_irq(host->irq, host); |
2132 | if (mmc_slot(host).card_detect_irq) | 2115 | if (mmc_slot(host).card_detect_irq) |
2133 | free_irq(mmc_slot(host).card_detect_irq, host); | 2116 | free_irq(mmc_slot(host).card_detect_irq, host); |
2134 | flush_work_sync(&host->mmc_carddetect_work); | ||
2135 | 2117 | ||
2136 | pm_runtime_put_sync(host->dev); | 2118 | pm_runtime_put_sync(host->dev); |
2137 | pm_runtime_disable(host->dev); | 2119 | pm_runtime_disable(host->dev); |
@@ -2178,7 +2160,6 @@ static int omap_hsmmc_suspend(struct device *dev) | |||
2178 | return ret; | 2160 | return ret; |
2179 | } | 2161 | } |
2180 | } | 2162 | } |
2181 | cancel_work_sync(&host->mmc_carddetect_work); | ||
2182 | ret = mmc_suspend_host(host->mmc); | 2163 | ret = mmc_suspend_host(host->mmc); |
2183 | 2164 | ||
2184 | if (ret) { | 2165 | if (ret) { |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index fc4356e00d46..cb2dc0e75ba7 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
@@ -872,18 +872,7 @@ static struct platform_driver pxamci_driver = { | |||
872 | }, | 872 | }, |
873 | }; | 873 | }; |
874 | 874 | ||
875 | static int __init pxamci_init(void) | 875 | module_platform_driver(pxamci_driver); |
876 | { | ||
877 | return platform_driver_register(&pxamci_driver); | ||
878 | } | ||
879 | |||
880 | static void __exit pxamci_exit(void) | ||
881 | { | ||
882 | platform_driver_unregister(&pxamci_driver); | ||
883 | } | ||
884 | |||
885 | module_init(pxamci_init); | ||
886 | module_exit(pxamci_exit); | ||
887 | 876 | ||
888 | MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver"); | 877 | MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver"); |
889 | MODULE_LICENSE("GPL"); | 878 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 720f99334a7f..1bcfd6dbb5cc 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
@@ -1914,18 +1914,7 @@ static struct platform_driver s3cmci_driver = { | |||
1914 | .shutdown = s3cmci_shutdown, | 1914 | .shutdown = s3cmci_shutdown, |
1915 | }; | 1915 | }; |
1916 | 1916 | ||
1917 | static int __init s3cmci_init(void) | 1917 | module_platform_driver(s3cmci_driver); |
1918 | { | ||
1919 | return platform_driver_register(&s3cmci_driver); | ||
1920 | } | ||
1921 | |||
1922 | static void __exit s3cmci_exit(void) | ||
1923 | { | ||
1924 | platform_driver_unregister(&s3cmci_driver); | ||
1925 | } | ||
1926 | |||
1927 | module_init(s3cmci_init); | ||
1928 | module_exit(s3cmci_exit); | ||
1929 | 1918 | ||
1930 | MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver"); | 1919 | MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver"); |
1931 | MODULE_LICENSE("GPL v2"); | 1920 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c index b4257e700617..28a870804f60 100644 --- a/drivers/mmc/host/sdhci-cns3xxx.c +++ b/drivers/mmc/host/sdhci-cns3xxx.c | |||
@@ -115,17 +115,7 @@ static struct platform_driver sdhci_cns3xxx_driver = { | |||
115 | .remove = __devexit_p(sdhci_cns3xxx_remove), | 115 | .remove = __devexit_p(sdhci_cns3xxx_remove), |
116 | }; | 116 | }; |
117 | 117 | ||
118 | static int __init sdhci_cns3xxx_init(void) | 118 | module_platform_driver(sdhci_cns3xxx_driver); |
119 | { | ||
120 | return platform_driver_register(&sdhci_cns3xxx_driver); | ||
121 | } | ||
122 | module_init(sdhci_cns3xxx_init); | ||
123 | |||
124 | static void __exit sdhci_cns3xxx_exit(void) | ||
125 | { | ||
126 | platform_driver_unregister(&sdhci_cns3xxx_driver); | ||
127 | } | ||
128 | module_exit(sdhci_cns3xxx_exit); | ||
129 | 119 | ||
130 | MODULE_DESCRIPTION("SDHCI driver for CNS3xxx"); | 120 | MODULE_DESCRIPTION("SDHCI driver for CNS3xxx"); |
131 | MODULE_AUTHOR("Scott Shu, " | 121 | MODULE_AUTHOR("Scott Shu, " |
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index a81312c91f70..46fd1fd1b605 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c | |||
@@ -88,17 +88,7 @@ static struct platform_driver sdhci_dove_driver = { | |||
88 | .remove = __devexit_p(sdhci_dove_remove), | 88 | .remove = __devexit_p(sdhci_dove_remove), |
89 | }; | 89 | }; |
90 | 90 | ||
91 | static int __init sdhci_dove_init(void) | 91 | module_platform_driver(sdhci_dove_driver); |
92 | { | ||
93 | return platform_driver_register(&sdhci_dove_driver); | ||
94 | } | ||
95 | module_init(sdhci_dove_init); | ||
96 | |||
97 | static void __exit sdhci_dove_exit(void) | ||
98 | { | ||
99 | platform_driver_unregister(&sdhci_dove_driver); | ||
100 | } | ||
101 | module_exit(sdhci_dove_exit); | ||
102 | 92 | ||
103 | MODULE_DESCRIPTION("SDHCI driver for Dove"); | 93 | MODULE_DESCRIPTION("SDHCI driver for Dove"); |
104 | MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>, " | 94 | MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>, " |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 38ebc4ea259f..d601e41af282 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
@@ -606,17 +606,7 @@ static struct platform_driver sdhci_esdhc_imx_driver = { | |||
606 | .remove = __devexit_p(sdhci_esdhc_imx_remove), | 606 | .remove = __devexit_p(sdhci_esdhc_imx_remove), |
607 | }; | 607 | }; |
608 | 608 | ||
609 | static int __init sdhci_esdhc_imx_init(void) | 609 | module_platform_driver(sdhci_esdhc_imx_driver); |
610 | { | ||
611 | return platform_driver_register(&sdhci_esdhc_imx_driver); | ||
612 | } | ||
613 | module_init(sdhci_esdhc_imx_init); | ||
614 | |||
615 | static void __exit sdhci_esdhc_imx_exit(void) | ||
616 | { | ||
617 | platform_driver_unregister(&sdhci_esdhc_imx_driver); | ||
618 | } | ||
619 | module_exit(sdhci_esdhc_imx_exit); | ||
620 | 610 | ||
621 | MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC"); | 611 | MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC"); |
622 | MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); | 612 | MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); |
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index c3b08f111942..b97b2f5dafdb 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h | |||
@@ -73,7 +73,7 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) | |||
73 | | (div << ESDHC_DIVIDER_SHIFT) | 73 | | (div << ESDHC_DIVIDER_SHIFT) |
74 | | (pre_div << ESDHC_PREDIV_SHIFT)); | 74 | | (pre_div << ESDHC_PREDIV_SHIFT)); |
75 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | 75 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); |
76 | mdelay(100); | 76 | mdelay(1); |
77 | out: | 77 | out: |
78 | host->clock = clock; | 78 | host->clock = clock; |
79 | } | 79 | } |
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 01e5f627e0f0..ff4adc018041 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
@@ -131,17 +131,7 @@ static struct platform_driver sdhci_esdhc_driver = { | |||
131 | .remove = __devexit_p(sdhci_esdhc_remove), | 131 | .remove = __devexit_p(sdhci_esdhc_remove), |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static int __init sdhci_esdhc_init(void) | 134 | module_platform_driver(sdhci_esdhc_driver); |
135 | { | ||
136 | return platform_driver_register(&sdhci_esdhc_driver); | ||
137 | } | ||
138 | module_init(sdhci_esdhc_init); | ||
139 | |||
140 | static void __exit sdhci_esdhc_exit(void) | ||
141 | { | ||
142 | platform_driver_unregister(&sdhci_esdhc_driver); | ||
143 | } | ||
144 | module_exit(sdhci_esdhc_exit); | ||
145 | 135 | ||
146 | MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC"); | 136 | MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC"); |
147 | MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, " | 137 | MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, " |
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c index 3619adc7d9fc..0ce088ae0228 100644 --- a/drivers/mmc/host/sdhci-of-hlwd.c +++ b/drivers/mmc/host/sdhci-of-hlwd.c | |||
@@ -93,17 +93,7 @@ static struct platform_driver sdhci_hlwd_driver = { | |||
93 | .remove = __devexit_p(sdhci_hlwd_remove), | 93 | .remove = __devexit_p(sdhci_hlwd_remove), |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static int __init sdhci_hlwd_init(void) | 96 | module_platform_driver(sdhci_hlwd_driver); |
97 | { | ||
98 | return platform_driver_register(&sdhci_hlwd_driver); | ||
99 | } | ||
100 | module_init(sdhci_hlwd_init); | ||
101 | |||
102 | static void __exit sdhci_hlwd_exit(void) | ||
103 | { | ||
104 | platform_driver_unregister(&sdhci_hlwd_driver); | ||
105 | } | ||
106 | module_exit(sdhci_hlwd_exit); | ||
107 | 97 | ||
108 | MODULE_DESCRIPTION("Nintendo Wii SDHCI OF driver"); | 98 | MODULE_DESCRIPTION("Nintendo Wii SDHCI OF driver"); |
109 | MODULE_AUTHOR("The GameCube Linux Team, Albert Herranz"); | 99 | MODULE_AUTHOR("The GameCube Linux Team, Albert Herranz"); |
diff --git a/drivers/mmc/host/sdhci-pci-data.c b/drivers/mmc/host/sdhci-pci-data.c new file mode 100644 index 000000000000..a611217769f5 --- /dev/null +++ b/drivers/mmc/host/sdhci-pci-data.c | |||
@@ -0,0 +1,5 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/mmc/sdhci-pci-data.h> | ||
3 | |||
4 | struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno); | ||
5 | EXPORT_SYMBOL_GPL(sdhci_pci_get_data); | ||
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 6878a94626bc..7165e6a09274 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #include <linux/scatterlist.h> | 23 | #include <linux/scatterlist.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
26 | #include <linux/sfi.h> | ||
27 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
27 | #include <linux/mmc/sdhci-pci-data.h> | ||
28 | 28 | ||
29 | #include "sdhci.h" | 29 | #include "sdhci.h" |
30 | 30 | ||
@@ -61,6 +61,7 @@ struct sdhci_pci_fixes { | |||
61 | struct sdhci_pci_slot { | 61 | struct sdhci_pci_slot { |
62 | struct sdhci_pci_chip *chip; | 62 | struct sdhci_pci_chip *chip; |
63 | struct sdhci_host *host; | 63 | struct sdhci_host *host; |
64 | struct sdhci_pci_data *data; | ||
64 | 65 | ||
65 | int pci_bar; | 66 | int pci_bar; |
66 | int rst_n_gpio; | 67 | int rst_n_gpio; |
@@ -171,32 +172,9 @@ static int mrst_hc_probe(struct sdhci_pci_chip *chip) | |||
171 | return 0; | 172 | return 0; |
172 | } | 173 | } |
173 | 174 | ||
174 | /* Medfield eMMC hardware reset GPIOs */ | ||
175 | static int mfd_emmc0_rst_gpio = -EINVAL; | ||
176 | static int mfd_emmc1_rst_gpio = -EINVAL; | ||
177 | |||
178 | static int mfd_emmc_gpio_parse(struct sfi_table_header *table) | ||
179 | { | ||
180 | struct sfi_table_simple *sb = (struct sfi_table_simple *)table; | ||
181 | struct sfi_gpio_table_entry *entry; | ||
182 | int i, num; | ||
183 | |||
184 | num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry); | ||
185 | entry = (struct sfi_gpio_table_entry *)sb->pentry; | ||
186 | |||
187 | for (i = 0; i < num; i++, entry++) { | ||
188 | if (!strncmp(entry->pin_name, "emmc0_rst", SFI_NAME_LEN)) | ||
189 | mfd_emmc0_rst_gpio = entry->pin_no; | ||
190 | else if (!strncmp(entry->pin_name, "emmc1_rst", SFI_NAME_LEN)) | ||
191 | mfd_emmc1_rst_gpio = entry->pin_no; | ||
192 | } | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | #ifdef CONFIG_PM_RUNTIME | 175 | #ifdef CONFIG_PM_RUNTIME |
198 | 176 | ||
199 | static irqreturn_t mfd_sd_cd(int irq, void *dev_id) | 177 | static irqreturn_t sdhci_pci_sd_cd(int irq, void *dev_id) |
200 | { | 178 | { |
201 | struct sdhci_pci_slot *slot = dev_id; | 179 | struct sdhci_pci_slot *slot = dev_id; |
202 | struct sdhci_host *host = slot->host; | 180 | struct sdhci_host *host = slot->host; |
@@ -205,15 +183,16 @@ static irqreturn_t mfd_sd_cd(int irq, void *dev_id) | |||
205 | return IRQ_HANDLED; | 183 | return IRQ_HANDLED; |
206 | } | 184 | } |
207 | 185 | ||
208 | #define MFLD_SD_CD_PIN 69 | 186 | static void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot) |
209 | |||
210 | static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot) | ||
211 | { | 187 | { |
212 | int err, irq, gpio = MFLD_SD_CD_PIN; | 188 | int err, irq, gpio = slot->cd_gpio; |
213 | 189 | ||
214 | slot->cd_gpio = -EINVAL; | 190 | slot->cd_gpio = -EINVAL; |
215 | slot->cd_irq = -EINVAL; | 191 | slot->cd_irq = -EINVAL; |
216 | 192 | ||
193 | if (!gpio_is_valid(gpio)) | ||
194 | return; | ||
195 | |||
217 | err = gpio_request(gpio, "sd_cd"); | 196 | err = gpio_request(gpio, "sd_cd"); |
218 | if (err < 0) | 197 | if (err < 0) |
219 | goto out; | 198 | goto out; |
@@ -226,72 +205,53 @@ static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot) | |||
226 | if (irq < 0) | 205 | if (irq < 0) |
227 | goto out_free; | 206 | goto out_free; |
228 | 207 | ||
229 | err = request_irq(irq, mfd_sd_cd, IRQF_TRIGGER_RISING | | 208 | err = request_irq(irq, sdhci_pci_sd_cd, IRQF_TRIGGER_RISING | |
230 | IRQF_TRIGGER_FALLING, "sd_cd", slot); | 209 | IRQF_TRIGGER_FALLING, "sd_cd", slot); |
231 | if (err) | 210 | if (err) |
232 | goto out_free; | 211 | goto out_free; |
233 | 212 | ||
234 | slot->cd_gpio = gpio; | 213 | slot->cd_gpio = gpio; |
235 | slot->cd_irq = irq; | 214 | slot->cd_irq = irq; |
236 | slot->host->quirks2 |= SDHCI_QUIRK2_OWN_CARD_DETECTION; | ||
237 | 215 | ||
238 | return 0; | 216 | return; |
239 | 217 | ||
240 | out_free: | 218 | out_free: |
241 | gpio_free(gpio); | 219 | gpio_free(gpio); |
242 | out: | 220 | out: |
243 | dev_warn(&slot->chip->pdev->dev, "failed to setup card detect wake up\n"); | 221 | dev_warn(&slot->chip->pdev->dev, "failed to setup card detect wake up\n"); |
244 | return 0; | ||
245 | } | 222 | } |
246 | 223 | ||
247 | static void mfd_sd_remove_slot(struct sdhci_pci_slot *slot, int dead) | 224 | static void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot) |
248 | { | 225 | { |
249 | if (slot->cd_irq >= 0) | 226 | if (slot->cd_irq >= 0) |
250 | free_irq(slot->cd_irq, slot); | 227 | free_irq(slot->cd_irq, slot); |
251 | gpio_free(slot->cd_gpio); | 228 | if (gpio_is_valid(slot->cd_gpio)) |
229 | gpio_free(slot->cd_gpio); | ||
252 | } | 230 | } |
253 | 231 | ||
254 | #else | 232 | #else |
255 | 233 | ||
256 | #define mfd_sd_probe_slot NULL | 234 | static inline void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot) |
257 | #define mfd_sd_remove_slot NULL | 235 | { |
236 | } | ||
237 | |||
238 | static inline void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot) | ||
239 | { | ||
240 | } | ||
258 | 241 | ||
259 | #endif | 242 | #endif |
260 | 243 | ||
261 | static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot) | 244 | static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot) |
262 | { | 245 | { |
263 | const char *name = NULL; | ||
264 | int gpio = -EINVAL; | ||
265 | |||
266 | sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, mfd_emmc_gpio_parse); | ||
267 | |||
268 | switch (slot->chip->pdev->device) { | ||
269 | case PCI_DEVICE_ID_INTEL_MFD_EMMC0: | ||
270 | gpio = mfd_emmc0_rst_gpio; | ||
271 | name = "eMMC0_reset"; | ||
272 | break; | ||
273 | case PCI_DEVICE_ID_INTEL_MFD_EMMC1: | ||
274 | gpio = mfd_emmc1_rst_gpio; | ||
275 | name = "eMMC1_reset"; | ||
276 | break; | ||
277 | } | ||
278 | |||
279 | if (!gpio_request(gpio, name)) { | ||
280 | gpio_direction_output(gpio, 1); | ||
281 | slot->rst_n_gpio = gpio; | ||
282 | slot->host->mmc->caps |= MMC_CAP_HW_RESET; | ||
283 | } | ||
284 | |||
285 | slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE; | 246 | slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE; |
286 | |||
287 | slot->host->mmc->caps2 = MMC_CAP2_BOOTPART_NOACC; | 247 | slot->host->mmc->caps2 = MMC_CAP2_BOOTPART_NOACC; |
288 | |||
289 | return 0; | 248 | return 0; |
290 | } | 249 | } |
291 | 250 | ||
292 | static void mfd_emmc_remove_slot(struct sdhci_pci_slot *slot, int dead) | 251 | static int mfd_sdio_probe_slot(struct sdhci_pci_slot *slot) |
293 | { | 252 | { |
294 | gpio_free(slot->rst_n_gpio); | 253 | slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD; |
254 | return 0; | ||
295 | } | 255 | } |
296 | 256 | ||
297 | static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = { | 257 | static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = { |
@@ -307,20 +267,18 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = { | |||
307 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { | 267 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { |
308 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 268 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
309 | .allow_runtime_pm = true, | 269 | .allow_runtime_pm = true, |
310 | .probe_slot = mfd_sd_probe_slot, | ||
311 | .remove_slot = mfd_sd_remove_slot, | ||
312 | }; | 270 | }; |
313 | 271 | ||
314 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = { | 272 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = { |
315 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 273 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
316 | .allow_runtime_pm = true, | 274 | .allow_runtime_pm = true, |
275 | .probe_slot = mfd_sdio_probe_slot, | ||
317 | }; | 276 | }; |
318 | 277 | ||
319 | static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = { | 278 | static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = { |
320 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 279 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
321 | .allow_runtime_pm = true, | 280 | .allow_runtime_pm = true, |
322 | .probe_slot = mfd_emmc_probe_slot, | 281 | .probe_slot = mfd_emmc_probe_slot, |
323 | .remove_slot = mfd_emmc_remove_slot, | ||
324 | }; | 282 | }; |
325 | 283 | ||
326 | /* O2Micro extra registers */ | 284 | /* O2Micro extra registers */ |
@@ -1012,11 +970,8 @@ static int sdhci_pci_suspend(struct device *dev) | |||
1012 | 970 | ||
1013 | ret = sdhci_suspend_host(slot->host); | 971 | ret = sdhci_suspend_host(slot->host); |
1014 | 972 | ||
1015 | if (ret) { | 973 | if (ret) |
1016 | for (i--; i >= 0; i--) | 974 | goto err_pci_suspend; |
1017 | sdhci_resume_host(chip->slots[i]->host); | ||
1018 | return ret; | ||
1019 | } | ||
1020 | 975 | ||
1021 | slot_pm_flags = slot->host->mmc->pm_flags; | 976 | slot_pm_flags = slot->host->mmc->pm_flags; |
1022 | if (slot_pm_flags & MMC_PM_WAKE_SDIO_IRQ) | 977 | if (slot_pm_flags & MMC_PM_WAKE_SDIO_IRQ) |
@@ -1027,11 +982,8 @@ static int sdhci_pci_suspend(struct device *dev) | |||
1027 | 982 | ||
1028 | if (chip->fixes && chip->fixes->suspend) { | 983 | if (chip->fixes && chip->fixes->suspend) { |
1029 | ret = chip->fixes->suspend(chip); | 984 | ret = chip->fixes->suspend(chip); |
1030 | if (ret) { | 985 | if (ret) |
1031 | for (i = chip->num_slots - 1; i >= 0; i--) | 986 | goto err_pci_suspend; |
1032 | sdhci_resume_host(chip->slots[i]->host); | ||
1033 | return ret; | ||
1034 | } | ||
1035 | } | 987 | } |
1036 | 988 | ||
1037 | pci_save_state(pdev); | 989 | pci_save_state(pdev); |
@@ -1048,6 +1000,11 @@ static int sdhci_pci_suspend(struct device *dev) | |||
1048 | } | 1000 | } |
1049 | 1001 | ||
1050 | return 0; | 1002 | return 0; |
1003 | |||
1004 | err_pci_suspend: | ||
1005 | while (--i >= 0) | ||
1006 | sdhci_resume_host(chip->slots[i]->host); | ||
1007 | return ret; | ||
1051 | } | 1008 | } |
1052 | 1009 | ||
1053 | static int sdhci_pci_resume(struct device *dev) | 1010 | static int sdhci_pci_resume(struct device *dev) |
@@ -1113,23 +1070,22 @@ static int sdhci_pci_runtime_suspend(struct device *dev) | |||
1113 | 1070 | ||
1114 | ret = sdhci_runtime_suspend_host(slot->host); | 1071 | ret = sdhci_runtime_suspend_host(slot->host); |
1115 | 1072 | ||
1116 | if (ret) { | 1073 | if (ret) |
1117 | for (i--; i >= 0; i--) | 1074 | goto err_pci_runtime_suspend; |
1118 | sdhci_runtime_resume_host(chip->slots[i]->host); | ||
1119 | return ret; | ||
1120 | } | ||
1121 | } | 1075 | } |
1122 | 1076 | ||
1123 | if (chip->fixes && chip->fixes->suspend) { | 1077 | if (chip->fixes && chip->fixes->suspend) { |
1124 | ret = chip->fixes->suspend(chip); | 1078 | ret = chip->fixes->suspend(chip); |
1125 | if (ret) { | 1079 | if (ret) |
1126 | for (i = chip->num_slots - 1; i >= 0; i--) | 1080 | goto err_pci_runtime_suspend; |
1127 | sdhci_runtime_resume_host(chip->slots[i]->host); | ||
1128 | return ret; | ||
1129 | } | ||
1130 | } | 1081 | } |
1131 | 1082 | ||
1132 | return 0; | 1083 | return 0; |
1084 | |||
1085 | err_pci_runtime_suspend: | ||
1086 | while (--i >= 0) | ||
1087 | sdhci_runtime_resume_host(chip->slots[i]->host); | ||
1088 | return ret; | ||
1133 | } | 1089 | } |
1134 | 1090 | ||
1135 | static int sdhci_pci_runtime_resume(struct device *dev) | 1091 | static int sdhci_pci_runtime_resume(struct device *dev) |
@@ -1190,11 +1146,12 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = { | |||
1190 | \*****************************************************************************/ | 1146 | \*****************************************************************************/ |
1191 | 1147 | ||
1192 | static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( | 1148 | static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( |
1193 | struct pci_dev *pdev, struct sdhci_pci_chip *chip, int bar) | 1149 | struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar, |
1150 | int slotno) | ||
1194 | { | 1151 | { |
1195 | struct sdhci_pci_slot *slot; | 1152 | struct sdhci_pci_slot *slot; |
1196 | struct sdhci_host *host; | 1153 | struct sdhci_host *host; |
1197 | int ret; | 1154 | int ret, bar = first_bar + slotno; |
1198 | 1155 | ||
1199 | if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) { | 1156 | if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) { |
1200 | dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar); | 1157 | dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar); |
@@ -1228,6 +1185,23 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( | |||
1228 | slot->host = host; | 1185 | slot->host = host; |
1229 | slot->pci_bar = bar; | 1186 | slot->pci_bar = bar; |
1230 | slot->rst_n_gpio = -EINVAL; | 1187 | slot->rst_n_gpio = -EINVAL; |
1188 | slot->cd_gpio = -EINVAL; | ||
1189 | |||
1190 | /* Retrieve platform data if there is any */ | ||
1191 | if (*sdhci_pci_get_data) | ||
1192 | slot->data = sdhci_pci_get_data(pdev, slotno); | ||
1193 | |||
1194 | if (slot->data) { | ||
1195 | if (slot->data->setup) { | ||
1196 | ret = slot->data->setup(slot->data); | ||
1197 | if (ret) { | ||
1198 | dev_err(&pdev->dev, "platform setup failed\n"); | ||
1199 | goto free; | ||
1200 | } | ||
1201 | } | ||
1202 | slot->rst_n_gpio = slot->data->rst_n_gpio; | ||
1203 | slot->cd_gpio = slot->data->cd_gpio; | ||
1204 | } | ||
1231 | 1205 | ||
1232 | host->hw_name = "PCI"; | 1206 | host->hw_name = "PCI"; |
1233 | host->ops = &sdhci_pci_ops; | 1207 | host->ops = &sdhci_pci_ops; |
@@ -1238,7 +1212,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( | |||
1238 | ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc)); | 1212 | ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc)); |
1239 | if (ret) { | 1213 | if (ret) { |
1240 | dev_err(&pdev->dev, "cannot request region\n"); | 1214 | dev_err(&pdev->dev, "cannot request region\n"); |
1241 | goto free; | 1215 | goto cleanup; |
1242 | } | 1216 | } |
1243 | 1217 | ||
1244 | host->ioaddr = pci_ioremap_bar(pdev, bar); | 1218 | host->ioaddr = pci_ioremap_bar(pdev, bar); |
@@ -1254,15 +1228,30 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( | |||
1254 | goto unmap; | 1228 | goto unmap; |
1255 | } | 1229 | } |
1256 | 1230 | ||
1231 | if (gpio_is_valid(slot->rst_n_gpio)) { | ||
1232 | if (!gpio_request(slot->rst_n_gpio, "eMMC_reset")) { | ||
1233 | gpio_direction_output(slot->rst_n_gpio, 1); | ||
1234 | slot->host->mmc->caps |= MMC_CAP_HW_RESET; | ||
1235 | } else { | ||
1236 | dev_warn(&pdev->dev, "failed to request rst_n_gpio\n"); | ||
1237 | slot->rst_n_gpio = -EINVAL; | ||
1238 | } | ||
1239 | } | ||
1240 | |||
1257 | host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; | 1241 | host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; |
1258 | 1242 | ||
1259 | ret = sdhci_add_host(host); | 1243 | ret = sdhci_add_host(host); |
1260 | if (ret) | 1244 | if (ret) |
1261 | goto remove; | 1245 | goto remove; |
1262 | 1246 | ||
1247 | sdhci_pci_add_own_cd(slot); | ||
1248 | |||
1263 | return slot; | 1249 | return slot; |
1264 | 1250 | ||
1265 | remove: | 1251 | remove: |
1252 | if (gpio_is_valid(slot->rst_n_gpio)) | ||
1253 | gpio_free(slot->rst_n_gpio); | ||
1254 | |||
1266 | if (chip->fixes && chip->fixes->remove_slot) | 1255 | if (chip->fixes && chip->fixes->remove_slot) |
1267 | chip->fixes->remove_slot(slot, 0); | 1256 | chip->fixes->remove_slot(slot, 0); |
1268 | 1257 | ||
@@ -1272,6 +1261,10 @@ unmap: | |||
1272 | release: | 1261 | release: |
1273 | pci_release_region(pdev, bar); | 1262 | pci_release_region(pdev, bar); |
1274 | 1263 | ||
1264 | cleanup: | ||
1265 | if (slot->data && slot->data->cleanup) | ||
1266 | slot->data->cleanup(slot->data); | ||
1267 | |||
1275 | free: | 1268 | free: |
1276 | sdhci_free_host(host); | 1269 | sdhci_free_host(host); |
1277 | 1270 | ||
@@ -1283,6 +1276,8 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) | |||
1283 | int dead; | 1276 | int dead; |
1284 | u32 scratch; | 1277 | u32 scratch; |
1285 | 1278 | ||
1279 | sdhci_pci_remove_own_cd(slot); | ||
1280 | |||
1286 | dead = 0; | 1281 | dead = 0; |
1287 | scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS); | 1282 | scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS); |
1288 | if (scratch == (u32)-1) | 1283 | if (scratch == (u32)-1) |
@@ -1290,9 +1285,15 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) | |||
1290 | 1285 | ||
1291 | sdhci_remove_host(slot->host, dead); | 1286 | sdhci_remove_host(slot->host, dead); |
1292 | 1287 | ||
1288 | if (gpio_is_valid(slot->rst_n_gpio)) | ||
1289 | gpio_free(slot->rst_n_gpio); | ||
1290 | |||
1293 | if (slot->chip->fixes && slot->chip->fixes->remove_slot) | 1291 | if (slot->chip->fixes && slot->chip->fixes->remove_slot) |
1294 | slot->chip->fixes->remove_slot(slot, dead); | 1292 | slot->chip->fixes->remove_slot(slot, dead); |
1295 | 1293 | ||
1294 | if (slot->data && slot->data->cleanup) | ||
1295 | slot->data->cleanup(slot->data); | ||
1296 | |||
1296 | pci_release_region(slot->chip->pdev, slot->pci_bar); | 1297 | pci_release_region(slot->chip->pdev, slot->pci_bar); |
1297 | 1298 | ||
1298 | sdhci_free_host(slot->host); | 1299 | sdhci_free_host(slot->host); |
@@ -1379,7 +1380,7 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev, | |||
1379 | slots = chip->num_slots; /* Quirk may have changed this */ | 1380 | slots = chip->num_slots; /* Quirk may have changed this */ |
1380 | 1381 | ||
1381 | for (i = 0; i < slots; i++) { | 1382 | for (i = 0; i < slots; i++) { |
1382 | slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i); | 1383 | slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i); |
1383 | if (IS_ERR(slot)) { | 1384 | if (IS_ERR(slot)) { |
1384 | for (i--; i >= 0; i--) | 1385 | for (i--; i >= 0; i--) |
1385 | sdhci_pci_remove_slot(chip->slots[i]); | 1386 | sdhci_pci_remove_slot(chip->slots[i]); |
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index 7a039c3cb1f1..dbb75bfbcffb 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c | |||
@@ -223,18 +223,8 @@ static struct platform_driver sdhci_pxav2_driver = { | |||
223 | .probe = sdhci_pxav2_probe, | 223 | .probe = sdhci_pxav2_probe, |
224 | .remove = __devexit_p(sdhci_pxav2_remove), | 224 | .remove = __devexit_p(sdhci_pxav2_remove), |
225 | }; | 225 | }; |
226 | static int __init sdhci_pxav2_init(void) | ||
227 | { | ||
228 | return platform_driver_register(&sdhci_pxav2_driver); | ||
229 | } | ||
230 | |||
231 | static void __exit sdhci_pxav2_exit(void) | ||
232 | { | ||
233 | platform_driver_unregister(&sdhci_pxav2_driver); | ||
234 | } | ||
235 | 226 | ||
236 | module_init(sdhci_pxav2_init); | 227 | module_platform_driver(sdhci_pxav2_driver); |
237 | module_exit(sdhci_pxav2_exit); | ||
238 | 228 | ||
239 | MODULE_DESCRIPTION("SDHCI driver for pxav2"); | 229 | MODULE_DESCRIPTION("SDHCI driver for pxav2"); |
240 | MODULE_AUTHOR("Marvell International Ltd."); | 230 | MODULE_AUTHOR("Marvell International Ltd."); |
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 15673a7ee6a5..f29695683556 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c | |||
@@ -269,18 +269,8 @@ static struct platform_driver sdhci_pxav3_driver = { | |||
269 | .probe = sdhci_pxav3_probe, | 269 | .probe = sdhci_pxav3_probe, |
270 | .remove = __devexit_p(sdhci_pxav3_remove), | 270 | .remove = __devexit_p(sdhci_pxav3_remove), |
271 | }; | 271 | }; |
272 | static int __init sdhci_pxav3_init(void) | ||
273 | { | ||
274 | return platform_driver_register(&sdhci_pxav3_driver); | ||
275 | } | ||
276 | |||
277 | static void __exit sdhci_pxav3_exit(void) | ||
278 | { | ||
279 | platform_driver_unregister(&sdhci_pxav3_driver); | ||
280 | } | ||
281 | 272 | ||
282 | module_init(sdhci_pxav3_init); | 273 | module_platform_driver(sdhci_pxav3_driver); |
283 | module_exit(sdhci_pxav3_exit); | ||
284 | 274 | ||
285 | MODULE_DESCRIPTION("SDHCI driver for pxav3"); | 275 | MODULE_DESCRIPTION("SDHCI driver for pxav3"); |
286 | MODULE_AUTHOR("Marvell International Ltd."); | 276 | MODULE_AUTHOR("Marvell International Ltd."); |
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 9a20d1f55bb7..1af756ee0f9a 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
@@ -80,7 +80,7 @@ static void sdhci_s3c_check_sclk(struct sdhci_host *host) | |||
80 | 80 | ||
81 | tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; | 81 | tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; |
82 | tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; | 82 | tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; |
83 | writel(tmp, host->ioaddr + 0x80); | 83 | writel(tmp, host->ioaddr + S3C_SDHCI_CONTROL2); |
84 | } | 84 | } |
85 | } | 85 | } |
86 | 86 | ||
@@ -521,6 +521,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
521 | if (pdata->host_caps) | 521 | if (pdata->host_caps) |
522 | host->mmc->caps |= pdata->host_caps; | 522 | host->mmc->caps |= pdata->host_caps; |
523 | 523 | ||
524 | if (pdata->pm_caps) | ||
525 | host->mmc->pm_caps |= pdata->pm_caps; | ||
526 | |||
524 | host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | | 527 | host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | |
525 | SDHCI_QUIRK_32BIT_DMA_SIZE); | 528 | SDHCI_QUIRK_32BIT_DMA_SIZE); |
526 | 529 | ||
@@ -654,18 +657,7 @@ static struct platform_driver sdhci_s3c_driver = { | |||
654 | }, | 657 | }, |
655 | }; | 658 | }; |
656 | 659 | ||
657 | static int __init sdhci_s3c_init(void) | 660 | module_platform_driver(sdhci_s3c_driver); |
658 | { | ||
659 | return platform_driver_register(&sdhci_s3c_driver); | ||
660 | } | ||
661 | |||
662 | static void __exit sdhci_s3c_exit(void) | ||
663 | { | ||
664 | platform_driver_unregister(&sdhci_s3c_driver); | ||
665 | } | ||
666 | |||
667 | module_init(sdhci_s3c_init); | ||
668 | module_exit(sdhci_s3c_exit); | ||
669 | 661 | ||
670 | MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue"); | 662 | MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue"); |
671 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 663 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index 63cc8b6a1c9e..b7f8b33c5f19 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/pm.h> | ||
24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
25 | #include <linux/mmc/host.h> | 26 | #include <linux/mmc/host.h> |
26 | #include <linux/mmc/sdhci-spear.h> | 27 | #include <linux/mmc/sdhci-spear.h> |
@@ -271,26 +272,54 @@ static int __devexit sdhci_remove(struct platform_device *pdev) | |||
271 | return 0; | 272 | return 0; |
272 | } | 273 | } |
273 | 274 | ||
275 | #ifdef CONFIG_PM | ||
276 | static int sdhci_suspend(struct device *dev) | ||
277 | { | ||
278 | struct sdhci_host *host = dev_get_drvdata(dev); | ||
279 | struct spear_sdhci *sdhci = dev_get_platdata(dev); | ||
280 | int ret; | ||
281 | |||
282 | ret = sdhci_suspend_host(host); | ||
283 | if (!ret) | ||
284 | clk_disable(sdhci->clk); | ||
285 | |||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | static int sdhci_resume(struct device *dev) | ||
290 | { | ||
291 | struct sdhci_host *host = dev_get_drvdata(dev); | ||
292 | struct spear_sdhci *sdhci = dev_get_platdata(dev); | ||
293 | int ret; | ||
294 | |||
295 | ret = clk_enable(sdhci->clk); | ||
296 | if (ret) { | ||
297 | dev_dbg(dev, "Resume: Error enabling clock\n"); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | return sdhci_resume_host(host); | ||
302 | } | ||
303 | |||
304 | const struct dev_pm_ops sdhci_pm_ops = { | ||
305 | .suspend = sdhci_suspend, | ||
306 | .resume = sdhci_resume, | ||
307 | }; | ||
308 | #endif | ||
309 | |||
274 | static struct platform_driver sdhci_driver = { | 310 | static struct platform_driver sdhci_driver = { |
275 | .driver = { | 311 | .driver = { |
276 | .name = "sdhci", | 312 | .name = "sdhci", |
277 | .owner = THIS_MODULE, | 313 | .owner = THIS_MODULE, |
314 | #ifdef CONFIG_PM | ||
315 | .pm = &sdhci_pm_ops, | ||
316 | #endif | ||
278 | }, | 317 | }, |
279 | .probe = sdhci_probe, | 318 | .probe = sdhci_probe, |
280 | .remove = __devexit_p(sdhci_remove), | 319 | .remove = __devexit_p(sdhci_remove), |
281 | }; | 320 | }; |
282 | 321 | ||
283 | static int __init sdhci_init(void) | 322 | module_platform_driver(sdhci_driver); |
284 | { | ||
285 | return platform_driver_register(&sdhci_driver); | ||
286 | } | ||
287 | module_init(sdhci_init); | ||
288 | |||
289 | static void __exit sdhci_exit(void) | ||
290 | { | ||
291 | platform_driver_unregister(&sdhci_driver); | ||
292 | } | ||
293 | module_exit(sdhci_exit); | ||
294 | 323 | ||
295 | MODULE_DESCRIPTION("SPEAr Secure Digital Host Controller Interface driver"); | 324 | MODULE_DESCRIPTION("SPEAr Secure Digital Host Controller Interface driver"); |
296 | MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>"); | 325 | MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>"); |
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index e2e18d3f949c..78a36eba4df0 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
@@ -324,17 +324,7 @@ static struct platform_driver sdhci_tegra_driver = { | |||
324 | .remove = __devexit_p(sdhci_tegra_remove), | 324 | .remove = __devexit_p(sdhci_tegra_remove), |
325 | }; | 325 | }; |
326 | 326 | ||
327 | static int __init sdhci_tegra_init(void) | 327 | module_platform_driver(sdhci_tegra_driver); |
328 | { | ||
329 | return platform_driver_register(&sdhci_tegra_driver); | ||
330 | } | ||
331 | module_init(sdhci_tegra_init); | ||
332 | |||
333 | static void __exit sdhci_tegra_exit(void) | ||
334 | { | ||
335 | platform_driver_unregister(&sdhci_tegra_driver); | ||
336 | } | ||
337 | module_exit(sdhci_tegra_exit); | ||
338 | 328 | ||
339 | MODULE_DESCRIPTION("SDHCI driver for Tegra"); | 329 | MODULE_DESCRIPTION("SDHCI driver for Tegra"); |
340 | MODULE_AUTHOR(" Google, Inc."); | 330 | MODULE_AUTHOR(" Google, Inc."); |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 19ed580f2cab..8d66706824a6 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -49,7 +49,7 @@ static void sdhci_finish_data(struct sdhci_host *); | |||
49 | 49 | ||
50 | static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); | 50 | static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); |
51 | static void sdhci_finish_command(struct sdhci_host *); | 51 | static void sdhci_finish_command(struct sdhci_host *); |
52 | static int sdhci_execute_tuning(struct mmc_host *mmc); | 52 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); |
53 | static void sdhci_tuning_timer(unsigned long data); | 53 | static void sdhci_tuning_timer(unsigned long data); |
54 | 54 | ||
55 | #ifdef CONFIG_PM_RUNTIME | 55 | #ifdef CONFIG_PM_RUNTIME |
@@ -146,10 +146,8 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) | |||
146 | { | 146 | { |
147 | u32 present, irqs; | 147 | u32 present, irqs; |
148 | 148 | ||
149 | if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) | 149 | if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) || |
150 | return; | 150 | !mmc_card_is_removable(host->mmc)) |
151 | |||
152 | if (host->quirks2 & SDHCI_QUIRK2_OWN_CARD_DETECTION) | ||
153 | return; | 151 | return; |
154 | 152 | ||
155 | present = sdhci_readl(host, SDHCI_PRESENT_STATE) & | 153 | present = sdhci_readl(host, SDHCI_PRESENT_STATE) & |
@@ -214,6 +212,11 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) | |||
214 | 212 | ||
215 | if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) | 213 | if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) |
216 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); | 214 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); |
215 | |||
216 | if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { | ||
217 | if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL)) | ||
218 | host->ops->enable_dma(host); | ||
219 | } | ||
217 | } | 220 | } |
218 | 221 | ||
219 | static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); | 222 | static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); |
@@ -423,12 +426,12 @@ static void sdhci_transfer_pio(struct sdhci_host *host) | |||
423 | static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) | 426 | static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) |
424 | { | 427 | { |
425 | local_irq_save(*flags); | 428 | local_irq_save(*flags); |
426 | return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; | 429 | return kmap_atomic(sg_page(sg)) + sg->offset; |
427 | } | 430 | } |
428 | 431 | ||
429 | static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) | 432 | static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) |
430 | { | 433 | { |
431 | kunmap_atomic(buffer, KM_BIO_SRC_IRQ); | 434 | kunmap_atomic(buffer); |
432 | local_irq_restore(*flags); | 435 | local_irq_restore(*flags); |
433 | } | 436 | } |
434 | 437 | ||
@@ -1016,7 +1019,8 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
1016 | flags |= SDHCI_CMD_INDEX; | 1019 | flags |= SDHCI_CMD_INDEX; |
1017 | 1020 | ||
1018 | /* CMD19 is special in that the Data Present Select should be set */ | 1021 | /* CMD19 is special in that the Data Present Select should be set */ |
1019 | if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK)) | 1022 | if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK || |
1023 | cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) | ||
1020 | flags |= SDHCI_CMD_DATA; | 1024 | flags |= SDHCI_CMD_DATA; |
1021 | 1025 | ||
1022 | sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); | 1026 | sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); |
@@ -1066,12 +1070,15 @@ static void sdhci_finish_command(struct sdhci_host *host) | |||
1066 | static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | 1070 | static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) |
1067 | { | 1071 | { |
1068 | int div = 0; /* Initialized for compiler warning */ | 1072 | int div = 0; /* Initialized for compiler warning */ |
1073 | int real_div = div, clk_mul = 1; | ||
1069 | u16 clk = 0; | 1074 | u16 clk = 0; |
1070 | unsigned long timeout; | 1075 | unsigned long timeout; |
1071 | 1076 | ||
1072 | if (clock == host->clock) | 1077 | if (clock && clock == host->clock) |
1073 | return; | 1078 | return; |
1074 | 1079 | ||
1080 | host->mmc->actual_clock = 0; | ||
1081 | |||
1075 | if (host->ops->set_clock) { | 1082 | if (host->ops->set_clock) { |
1076 | host->ops->set_clock(host, clock); | 1083 | host->ops->set_clock(host, clock); |
1077 | if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) | 1084 | if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) |
@@ -1109,6 +1116,8 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
1109 | * Control register. | 1116 | * Control register. |
1110 | */ | 1117 | */ |
1111 | clk = SDHCI_PROG_CLOCK_MODE; | 1118 | clk = SDHCI_PROG_CLOCK_MODE; |
1119 | real_div = div; | ||
1120 | clk_mul = host->clk_mul; | ||
1112 | div--; | 1121 | div--; |
1113 | } | 1122 | } |
1114 | } else { | 1123 | } else { |
@@ -1122,6 +1131,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
1122 | break; | 1131 | break; |
1123 | } | 1132 | } |
1124 | } | 1133 | } |
1134 | real_div = div; | ||
1125 | div >>= 1; | 1135 | div >>= 1; |
1126 | } | 1136 | } |
1127 | } else { | 1137 | } else { |
@@ -1130,9 +1140,13 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
1130 | if ((host->max_clk / div) <= clock) | 1140 | if ((host->max_clk / div) <= clock) |
1131 | break; | 1141 | break; |
1132 | } | 1142 | } |
1143 | real_div = div; | ||
1133 | div >>= 1; | 1144 | div >>= 1; |
1134 | } | 1145 | } |
1135 | 1146 | ||
1147 | if (real_div) | ||
1148 | host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div; | ||
1149 | |||
1136 | clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; | 1150 | clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; |
1137 | clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) | 1151 | clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) |
1138 | << SDHCI_DIVIDER_HI_SHIFT; | 1152 | << SDHCI_DIVIDER_HI_SHIFT; |
@@ -1160,7 +1174,7 @@ out: | |||
1160 | host->clock = clock; | 1174 | host->clock = clock; |
1161 | } | 1175 | } |
1162 | 1176 | ||
1163 | static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | 1177 | static int sdhci_set_power(struct sdhci_host *host, unsigned short power) |
1164 | { | 1178 | { |
1165 | u8 pwr = 0; | 1179 | u8 pwr = 0; |
1166 | 1180 | ||
@@ -1183,13 +1197,13 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
1183 | } | 1197 | } |
1184 | 1198 | ||
1185 | if (host->pwr == pwr) | 1199 | if (host->pwr == pwr) |
1186 | return; | 1200 | return -1; |
1187 | 1201 | ||
1188 | host->pwr = pwr; | 1202 | host->pwr = pwr; |
1189 | 1203 | ||
1190 | if (pwr == 0) { | 1204 | if (pwr == 0) { |
1191 | sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); | 1205 | sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); |
1192 | return; | 1206 | return 0; |
1193 | } | 1207 | } |
1194 | 1208 | ||
1195 | /* | 1209 | /* |
@@ -1216,6 +1230,8 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
1216 | */ | 1230 | */ |
1217 | if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) | 1231 | if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) |
1218 | mdelay(10); | 1232 | mdelay(10); |
1233 | |||
1234 | return power; | ||
1219 | } | 1235 | } |
1220 | 1236 | ||
1221 | /*****************************************************************************\ | 1237 | /*****************************************************************************\ |
@@ -1277,7 +1293,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1277 | if ((host->flags & SDHCI_NEEDS_RETUNING) && | 1293 | if ((host->flags & SDHCI_NEEDS_RETUNING) && |
1278 | !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { | 1294 | !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { |
1279 | spin_unlock_irqrestore(&host->lock, flags); | 1295 | spin_unlock_irqrestore(&host->lock, flags); |
1280 | sdhci_execute_tuning(mmc); | 1296 | sdhci_execute_tuning(mmc, mrq->cmd->opcode); |
1281 | spin_lock_irqsave(&host->lock, flags); | 1297 | spin_lock_irqsave(&host->lock, flags); |
1282 | 1298 | ||
1283 | /* Restore original mmc_request structure */ | 1299 | /* Restore original mmc_request structure */ |
@@ -1297,12 +1313,17 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1297 | static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) | 1313 | static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) |
1298 | { | 1314 | { |
1299 | unsigned long flags; | 1315 | unsigned long flags; |
1316 | int vdd_bit = -1; | ||
1300 | u8 ctrl; | 1317 | u8 ctrl; |
1301 | 1318 | ||
1302 | spin_lock_irqsave(&host->lock, flags); | 1319 | spin_lock_irqsave(&host->lock, flags); |
1303 | 1320 | ||
1304 | if (host->flags & SDHCI_DEVICE_DEAD) | 1321 | if (host->flags & SDHCI_DEVICE_DEAD) { |
1305 | goto out; | 1322 | spin_unlock_irqrestore(&host->lock, flags); |
1323 | if (host->vmmc && ios->power_mode == MMC_POWER_OFF) | ||
1324 | mmc_regulator_set_ocr(host->mmc, host->vmmc, 0); | ||
1325 | return; | ||
1326 | } | ||
1306 | 1327 | ||
1307 | /* | 1328 | /* |
1308 | * Reset the chip on each power off. | 1329 | * Reset the chip on each power off. |
@@ -1316,9 +1337,15 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) | |||
1316 | sdhci_set_clock(host, ios->clock); | 1337 | sdhci_set_clock(host, ios->clock); |
1317 | 1338 | ||
1318 | if (ios->power_mode == MMC_POWER_OFF) | 1339 | if (ios->power_mode == MMC_POWER_OFF) |
1319 | sdhci_set_power(host, -1); | 1340 | vdd_bit = sdhci_set_power(host, -1); |
1320 | else | 1341 | else |
1321 | sdhci_set_power(host, ios->vdd); | 1342 | vdd_bit = sdhci_set_power(host, ios->vdd); |
1343 | |||
1344 | if (host->vmmc && vdd_bit != -1) { | ||
1345 | spin_unlock_irqrestore(&host->lock, flags); | ||
1346 | mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit); | ||
1347 | spin_lock_irqsave(&host->lock, flags); | ||
1348 | } | ||
1322 | 1349 | ||
1323 | if (host->ops->platform_send_init_74_clocks) | 1350 | if (host->ops->platform_send_init_74_clocks) |
1324 | host->ops->platform_send_init_74_clocks(host, ios->power_mode); | 1351 | host->ops->platform_send_init_74_clocks(host, ios->power_mode); |
@@ -1361,11 +1388,11 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) | |||
1361 | unsigned int clock; | 1388 | unsigned int clock; |
1362 | 1389 | ||
1363 | /* In case of UHS-I modes, set High Speed Enable */ | 1390 | /* In case of UHS-I modes, set High Speed Enable */ |
1364 | if ((ios->timing == MMC_TIMING_UHS_SDR50) || | 1391 | if ((ios->timing == MMC_TIMING_MMC_HS200) || |
1392 | (ios->timing == MMC_TIMING_UHS_SDR50) || | ||
1365 | (ios->timing == MMC_TIMING_UHS_SDR104) || | 1393 | (ios->timing == MMC_TIMING_UHS_SDR104) || |
1366 | (ios->timing == MMC_TIMING_UHS_DDR50) || | 1394 | (ios->timing == MMC_TIMING_UHS_DDR50) || |
1367 | (ios->timing == MMC_TIMING_UHS_SDR25) || | 1395 | (ios->timing == MMC_TIMING_UHS_SDR25)) |
1368 | (ios->timing == MMC_TIMING_UHS_SDR12)) | ||
1369 | ctrl |= SDHCI_CTRL_HISPD; | 1396 | ctrl |= SDHCI_CTRL_HISPD; |
1370 | 1397 | ||
1371 | ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1398 | ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
@@ -1415,7 +1442,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) | |||
1415 | ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1442 | ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
1416 | /* Select Bus Speed Mode for host */ | 1443 | /* Select Bus Speed Mode for host */ |
1417 | ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; | 1444 | ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; |
1418 | if (ios->timing == MMC_TIMING_UHS_SDR12) | 1445 | if (ios->timing == MMC_TIMING_MMC_HS200) |
1446 | ctrl_2 |= SDHCI_CTRL_HS_SDR200; | ||
1447 | else if (ios->timing == MMC_TIMING_UHS_SDR12) | ||
1419 | ctrl_2 |= SDHCI_CTRL_UHS_SDR12; | 1448 | ctrl_2 |= SDHCI_CTRL_UHS_SDR12; |
1420 | else if (ios->timing == MMC_TIMING_UHS_SDR25) | 1449 | else if (ios->timing == MMC_TIMING_UHS_SDR25) |
1421 | ctrl_2 |= SDHCI_CTRL_UHS_SDR25; | 1450 | ctrl_2 |= SDHCI_CTRL_UHS_SDR25; |
@@ -1443,7 +1472,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) | |||
1443 | if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) | 1472 | if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) |
1444 | sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); | 1473 | sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); |
1445 | 1474 | ||
1446 | out: | ||
1447 | mmiowb(); | 1475 | mmiowb(); |
1448 | spin_unlock_irqrestore(&host->lock, flags); | 1476 | spin_unlock_irqrestore(&host->lock, flags); |
1449 | } | 1477 | } |
@@ -1663,7 +1691,7 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, | |||
1663 | return err; | 1691 | return err; |
1664 | } | 1692 | } |
1665 | 1693 | ||
1666 | static int sdhci_execute_tuning(struct mmc_host *mmc) | 1694 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) |
1667 | { | 1695 | { |
1668 | struct sdhci_host *host; | 1696 | struct sdhci_host *host; |
1669 | u16 ctrl; | 1697 | u16 ctrl; |
@@ -1671,6 +1699,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc) | |||
1671 | int tuning_loop_counter = MAX_TUNING_LOOP; | 1699 | int tuning_loop_counter = MAX_TUNING_LOOP; |
1672 | unsigned long timeout; | 1700 | unsigned long timeout; |
1673 | int err = 0; | 1701 | int err = 0; |
1702 | bool requires_tuning_nonuhs = false; | ||
1674 | 1703 | ||
1675 | host = mmc_priv(mmc); | 1704 | host = mmc_priv(mmc); |
1676 | 1705 | ||
@@ -1681,13 +1710,19 @@ static int sdhci_execute_tuning(struct mmc_host *mmc) | |||
1681 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1710 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
1682 | 1711 | ||
1683 | /* | 1712 | /* |
1684 | * Host Controller needs tuning only in case of SDR104 mode | 1713 | * The Host Controller needs tuning only in case of SDR104 mode |
1685 | * and for SDR50 mode when Use Tuning for SDR50 is set in | 1714 | * and for SDR50 mode when Use Tuning for SDR50 is set in the |
1686 | * Capabilities register. | 1715 | * Capabilities register. |
1716 | * If the Host Controller supports the HS200 mode then the | ||
1717 | * tuning function has to be executed. | ||
1687 | */ | 1718 | */ |
1719 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && | ||
1720 | (host->flags & SDHCI_SDR50_NEEDS_TUNING || | ||
1721 | host->flags & SDHCI_HS200_NEEDS_TUNING)) | ||
1722 | requires_tuning_nonuhs = true; | ||
1723 | |||
1688 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || | 1724 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || |
1689 | (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && | 1725 | requires_tuning_nonuhs) |
1690 | (host->flags & SDHCI_SDR50_NEEDS_TUNING))) | ||
1691 | ctrl |= SDHCI_CTRL_EXEC_TUNING; | 1726 | ctrl |= SDHCI_CTRL_EXEC_TUNING; |
1692 | else { | 1727 | else { |
1693 | spin_unlock(&host->lock); | 1728 | spin_unlock(&host->lock); |
@@ -1723,7 +1758,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc) | |||
1723 | if (!tuning_loop_counter && !timeout) | 1758 | if (!tuning_loop_counter && !timeout) |
1724 | break; | 1759 | break; |
1725 | 1760 | ||
1726 | cmd.opcode = MMC_SEND_TUNING_BLOCK; | 1761 | cmd.opcode = opcode; |
1727 | cmd.arg = 0; | 1762 | cmd.arg = 0; |
1728 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | 1763 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; |
1729 | cmd.retries = 0; | 1764 | cmd.retries = 0; |
@@ -1738,7 +1773,17 @@ static int sdhci_execute_tuning(struct mmc_host *mmc) | |||
1738 | * block to the Host Controller. So we set the block size | 1773 | * block to the Host Controller. So we set the block size |
1739 | * to 64 here. | 1774 | * to 64 here. |
1740 | */ | 1775 | */ |
1741 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE); | 1776 | if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) { |
1777 | if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) | ||
1778 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128), | ||
1779 | SDHCI_BLOCK_SIZE); | ||
1780 | else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) | ||
1781 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), | ||
1782 | SDHCI_BLOCK_SIZE); | ||
1783 | } else { | ||
1784 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), | ||
1785 | SDHCI_BLOCK_SIZE); | ||
1786 | } | ||
1742 | 1787 | ||
1743 | /* | 1788 | /* |
1744 | * The tuning block is sent by the card to the host controller. | 1789 | * The tuning block is sent by the card to the host controller. |
@@ -2121,12 +2166,14 @@ static void sdhci_show_adma_error(struct sdhci_host *host) { } | |||
2121 | 2166 | ||
2122 | static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | 2167 | static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) |
2123 | { | 2168 | { |
2169 | u32 command; | ||
2124 | BUG_ON(intmask == 0); | 2170 | BUG_ON(intmask == 0); |
2125 | 2171 | ||
2126 | /* CMD19 generates _only_ Buffer Read Ready interrupt */ | 2172 | /* CMD19 generates _only_ Buffer Read Ready interrupt */ |
2127 | if (intmask & SDHCI_INT_DATA_AVAIL) { | 2173 | if (intmask & SDHCI_INT_DATA_AVAIL) { |
2128 | if (SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) == | 2174 | command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)); |
2129 | MMC_SEND_TUNING_BLOCK) { | 2175 | if (command == MMC_SEND_TUNING_BLOCK || |
2176 | command == MMC_SEND_TUNING_BLOCK_HS200) { | ||
2130 | host->tuning_done = 1; | 2177 | host->tuning_done = 1; |
2131 | wake_up(&host->buf_ready_int); | 2178 | wake_up(&host->buf_ready_int); |
2132 | return; | 2179 | return; |
@@ -2330,26 +2377,33 @@ out: | |||
2330 | int sdhci_suspend_host(struct sdhci_host *host) | 2377 | int sdhci_suspend_host(struct sdhci_host *host) |
2331 | { | 2378 | { |
2332 | int ret; | 2379 | int ret; |
2380 | bool has_tuning_timer; | ||
2333 | 2381 | ||
2334 | sdhci_disable_card_detection(host); | 2382 | sdhci_disable_card_detection(host); |
2335 | 2383 | ||
2336 | /* Disable tuning since we are suspending */ | 2384 | /* Disable tuning since we are suspending */ |
2337 | if (host->version >= SDHCI_SPEC_300 && host->tuning_count && | 2385 | has_tuning_timer = host->version >= SDHCI_SPEC_300 && |
2338 | host->tuning_mode == SDHCI_TUNING_MODE_1) { | 2386 | host->tuning_count && host->tuning_mode == SDHCI_TUNING_MODE_1; |
2387 | if (has_tuning_timer) { | ||
2388 | del_timer_sync(&host->tuning_timer); | ||
2339 | host->flags &= ~SDHCI_NEEDS_RETUNING; | 2389 | host->flags &= ~SDHCI_NEEDS_RETUNING; |
2340 | mod_timer(&host->tuning_timer, jiffies + | ||
2341 | host->tuning_count * HZ); | ||
2342 | } | 2390 | } |
2343 | 2391 | ||
2344 | ret = mmc_suspend_host(host->mmc); | 2392 | ret = mmc_suspend_host(host->mmc); |
2345 | if (ret) | 2393 | if (ret) { |
2394 | if (has_tuning_timer) { | ||
2395 | host->flags |= SDHCI_NEEDS_RETUNING; | ||
2396 | mod_timer(&host->tuning_timer, jiffies + | ||
2397 | host->tuning_count * HZ); | ||
2398 | } | ||
2399 | |||
2400 | sdhci_enable_card_detection(host); | ||
2401 | |||
2346 | return ret; | 2402 | return ret; |
2403 | } | ||
2347 | 2404 | ||
2348 | free_irq(host->irq, host); | 2405 | free_irq(host->irq, host); |
2349 | 2406 | ||
2350 | if (host->vmmc) | ||
2351 | ret = regulator_disable(host->vmmc); | ||
2352 | |||
2353 | return ret; | 2407 | return ret; |
2354 | } | 2408 | } |
2355 | 2409 | ||
@@ -2359,12 +2413,6 @@ int sdhci_resume_host(struct sdhci_host *host) | |||
2359 | { | 2413 | { |
2360 | int ret; | 2414 | int ret; |
2361 | 2415 | ||
2362 | if (host->vmmc) { | ||
2363 | int ret = regulator_enable(host->vmmc); | ||
2364 | if (ret) | ||
2365 | return ret; | ||
2366 | } | ||
2367 | |||
2368 | if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { | 2416 | if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { |
2369 | if (host->ops->enable_dma) | 2417 | if (host->ops->enable_dma) |
2370 | host->ops->enable_dma(host); | 2418 | host->ops->enable_dma(host); |
@@ -2727,10 +2775,14 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2727 | if (caps[1] & SDHCI_SUPPORT_DDR50) | 2775 | if (caps[1] & SDHCI_SUPPORT_DDR50) |
2728 | mmc->caps |= MMC_CAP_UHS_DDR50; | 2776 | mmc->caps |= MMC_CAP_UHS_DDR50; |
2729 | 2777 | ||
2730 | /* Does the host needs tuning for SDR50? */ | 2778 | /* Does the host need tuning for SDR50? */ |
2731 | if (caps[1] & SDHCI_USE_SDR50_TUNING) | 2779 | if (caps[1] & SDHCI_USE_SDR50_TUNING) |
2732 | host->flags |= SDHCI_SDR50_NEEDS_TUNING; | 2780 | host->flags |= SDHCI_SDR50_NEEDS_TUNING; |
2733 | 2781 | ||
2782 | /* Does the host need tuning for HS200? */ | ||
2783 | if (mmc->caps2 & MMC_CAP2_HS200) | ||
2784 | host->flags |= SDHCI_HS200_NEEDS_TUNING; | ||
2785 | |||
2734 | /* Driver Type(s) (A, C, D) supported by the host */ | 2786 | /* Driver Type(s) (A, C, D) supported by the host */ |
2735 | if (caps[1] & SDHCI_DRIVER_TYPE_A) | 2787 | if (caps[1] & SDHCI_DRIVER_TYPE_A) |
2736 | mmc->caps |= MMC_CAP_DRIVER_TYPE_A; | 2788 | mmc->caps |= MMC_CAP_DRIVER_TYPE_A; |
@@ -2926,8 +2978,6 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2926 | if (IS_ERR(host->vmmc)) { | 2978 | if (IS_ERR(host->vmmc)) { |
2927 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); | 2979 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); |
2928 | host->vmmc = NULL; | 2980 | host->vmmc = NULL; |
2929 | } else { | ||
2930 | regulator_enable(host->vmmc); | ||
2931 | } | 2981 | } |
2932 | 2982 | ||
2933 | sdhci_init(host, 0); | 2983 | sdhci_init(host, 0); |
@@ -3016,10 +3066,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) | |||
3016 | tasklet_kill(&host->card_tasklet); | 3066 | tasklet_kill(&host->card_tasklet); |
3017 | tasklet_kill(&host->finish_tasklet); | 3067 | tasklet_kill(&host->finish_tasklet); |
3018 | 3068 | ||
3019 | if (host->vmmc) { | 3069 | if (host->vmmc) |
3020 | regulator_disable(host->vmmc); | ||
3021 | regulator_put(host->vmmc); | 3070 | regulator_put(host->vmmc); |
3022 | } | ||
3023 | 3071 | ||
3024 | kfree(host->adma_desc); | 3072 | kfree(host->adma_desc); |
3025 | kfree(host->align_buffer); | 3073 | kfree(host->align_buffer); |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index a04d4d0c6fd2..ad265b96b75b 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -158,6 +158,7 @@ | |||
158 | #define SDHCI_CTRL_UHS_SDR50 0x0002 | 158 | #define SDHCI_CTRL_UHS_SDR50 0x0002 |
159 | #define SDHCI_CTRL_UHS_SDR104 0x0003 | 159 | #define SDHCI_CTRL_UHS_SDR104 0x0003 |
160 | #define SDHCI_CTRL_UHS_DDR50 0x0004 | 160 | #define SDHCI_CTRL_UHS_DDR50 0x0004 |
161 | #define SDHCI_CTRL_HS_SDR200 0x0005 /* reserved value in SDIO spec */ | ||
161 | #define SDHCI_CTRL_VDD_180 0x0008 | 162 | #define SDHCI_CTRL_VDD_180 0x0008 |
162 | #define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 | 163 | #define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 |
163 | #define SDHCI_CTRL_DRV_TYPE_B 0x0000 | 164 | #define SDHCI_CTRL_DRV_TYPE_B 0x0000 |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index d5505f3fe2a1..4a2c5b2355f2 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -16,6 +16,33 @@ | |||
16 | * | 16 | * |
17 | */ | 17 | */ |
18 | 18 | ||
19 | /* | ||
20 | * The MMCIF driver is now processing MMC requests asynchronously, according | ||
21 | * to the Linux MMC API requirement. | ||
22 | * | ||
23 | * The MMCIF driver processes MMC requests in up to 3 stages: command, optional | ||
24 | * data, and optional stop. To achieve asynchronous processing each of these | ||
25 | * stages is split into two halves: a top and a bottom half. The top half | ||
26 | * initialises the hardware, installs a timeout handler to handle completion | ||
27 | * timeouts, and returns. In case of the command stage this immediately returns | ||
28 | * control to the caller, leaving all further processing to run asynchronously. | ||
29 | * All further request processing is performed by the bottom halves. | ||
30 | * | ||
31 | * The bottom half further consists of a "hard" IRQ handler, an IRQ handler | ||
32 | * thread, a DMA completion callback, if DMA is used, a timeout work, and | ||
33 | * request- and stage-specific handler methods. | ||
34 | * | ||
35 | * Each bottom half run begins with either a hardware interrupt, a DMA callback | ||
36 | * invocation, or a timeout work run. In case of an error or a successful | ||
37 | * processing completion, the MMC core is informed and the request processing is | ||
38 | * finished. In case processing has to continue, i.e., if data has to be read | ||
39 | * from or written to the card, or if a stop command has to be sent, the next | ||
40 | * top half is called, which performs the necessary hardware handling and | ||
41 | * reschedules the timeout work. This returns the driver state machine into the | ||
42 | * bottom half waiting state. | ||
43 | */ | ||
44 | |||
45 | #include <linux/bitops.h> | ||
19 | #include <linux/clk.h> | 46 | #include <linux/clk.h> |
20 | #include <linux/completion.h> | 47 | #include <linux/completion.h> |
21 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
@@ -123,6 +150,11 @@ | |||
123 | #define MASK_MRBSYTO (1 << 1) | 150 | #define MASK_MRBSYTO (1 << 1) |
124 | #define MASK_MRSPTO (1 << 0) | 151 | #define MASK_MRSPTO (1 << 0) |
125 | 152 | ||
153 | #define MASK_START_CMD (MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | \ | ||
154 | MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | \ | ||
155 | MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \ | ||
156 | MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO) | ||
157 | |||
126 | /* CE_HOST_STS1 */ | 158 | /* CE_HOST_STS1 */ |
127 | #define STS1_CMDSEQ (1 << 31) | 159 | #define STS1_CMDSEQ (1 << 31) |
128 | 160 | ||
@@ -162,9 +194,21 @@ enum mmcif_state { | |||
162 | STATE_IOS, | 194 | STATE_IOS, |
163 | }; | 195 | }; |
164 | 196 | ||
197 | enum mmcif_wait_for { | ||
198 | MMCIF_WAIT_FOR_REQUEST, | ||
199 | MMCIF_WAIT_FOR_CMD, | ||
200 | MMCIF_WAIT_FOR_MREAD, | ||
201 | MMCIF_WAIT_FOR_MWRITE, | ||
202 | MMCIF_WAIT_FOR_READ, | ||
203 | MMCIF_WAIT_FOR_WRITE, | ||
204 | MMCIF_WAIT_FOR_READ_END, | ||
205 | MMCIF_WAIT_FOR_WRITE_END, | ||
206 | MMCIF_WAIT_FOR_STOP, | ||
207 | }; | ||
208 | |||
165 | struct sh_mmcif_host { | 209 | struct sh_mmcif_host { |
166 | struct mmc_host *mmc; | 210 | struct mmc_host *mmc; |
167 | struct mmc_data *data; | 211 | struct mmc_request *mrq; |
168 | struct platform_device *pd; | 212 | struct platform_device *pd; |
169 | struct sh_dmae_slave dma_slave_tx; | 213 | struct sh_dmae_slave dma_slave_tx; |
170 | struct sh_dmae_slave dma_slave_rx; | 214 | struct sh_dmae_slave dma_slave_rx; |
@@ -172,11 +216,17 @@ struct sh_mmcif_host { | |||
172 | unsigned int clk; | 216 | unsigned int clk; |
173 | int bus_width; | 217 | int bus_width; |
174 | bool sd_error; | 218 | bool sd_error; |
219 | bool dying; | ||
175 | long timeout; | 220 | long timeout; |
176 | void __iomem *addr; | 221 | void __iomem *addr; |
177 | struct completion intr_wait; | 222 | u32 *pio_ptr; |
223 | spinlock_t lock; /* protect sh_mmcif_host::state */ | ||
178 | enum mmcif_state state; | 224 | enum mmcif_state state; |
179 | spinlock_t lock; | 225 | enum mmcif_wait_for wait_for; |
226 | struct delayed_work timeout_work; | ||
227 | size_t blocksize; | ||
228 | int sg_idx; | ||
229 | int sg_blkidx; | ||
180 | bool power; | 230 | bool power; |
181 | bool card_present; | 231 | bool card_present; |
182 | 232 | ||
@@ -202,19 +252,21 @@ static inline void sh_mmcif_bitclr(struct sh_mmcif_host *host, | |||
202 | static void mmcif_dma_complete(void *arg) | 252 | static void mmcif_dma_complete(void *arg) |
203 | { | 253 | { |
204 | struct sh_mmcif_host *host = arg; | 254 | struct sh_mmcif_host *host = arg; |
255 | struct mmc_data *data = host->mrq->data; | ||
256 | |||
205 | dev_dbg(&host->pd->dev, "Command completed\n"); | 257 | dev_dbg(&host->pd->dev, "Command completed\n"); |
206 | 258 | ||
207 | if (WARN(!host->data, "%s: NULL data in DMA completion!\n", | 259 | if (WARN(!data, "%s: NULL data in DMA completion!\n", |
208 | dev_name(&host->pd->dev))) | 260 | dev_name(&host->pd->dev))) |
209 | return; | 261 | return; |
210 | 262 | ||
211 | if (host->data->flags & MMC_DATA_READ) | 263 | if (data->flags & MMC_DATA_READ) |
212 | dma_unmap_sg(host->chan_rx->device->dev, | 264 | dma_unmap_sg(host->chan_rx->device->dev, |
213 | host->data->sg, host->data->sg_len, | 265 | data->sg, data->sg_len, |
214 | DMA_FROM_DEVICE); | 266 | DMA_FROM_DEVICE); |
215 | else | 267 | else |
216 | dma_unmap_sg(host->chan_tx->device->dev, | 268 | dma_unmap_sg(host->chan_tx->device->dev, |
217 | host->data->sg, host->data->sg_len, | 269 | data->sg, data->sg_len, |
218 | DMA_TO_DEVICE); | 270 | DMA_TO_DEVICE); |
219 | 271 | ||
220 | complete(&host->dma_complete); | 272 | complete(&host->dma_complete); |
@@ -222,13 +274,14 @@ static void mmcif_dma_complete(void *arg) | |||
222 | 274 | ||
223 | static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) | 275 | static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) |
224 | { | 276 | { |
225 | struct scatterlist *sg = host->data->sg; | 277 | struct mmc_data *data = host->mrq->data; |
278 | struct scatterlist *sg = data->sg; | ||
226 | struct dma_async_tx_descriptor *desc = NULL; | 279 | struct dma_async_tx_descriptor *desc = NULL; |
227 | struct dma_chan *chan = host->chan_rx; | 280 | struct dma_chan *chan = host->chan_rx; |
228 | dma_cookie_t cookie = -EINVAL; | 281 | dma_cookie_t cookie = -EINVAL; |
229 | int ret; | 282 | int ret; |
230 | 283 | ||
231 | ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len, | 284 | ret = dma_map_sg(chan->device->dev, sg, data->sg_len, |
232 | DMA_FROM_DEVICE); | 285 | DMA_FROM_DEVICE); |
233 | if (ret > 0) { | 286 | if (ret > 0) { |
234 | host->dma_active = true; | 287 | host->dma_active = true; |
@@ -244,7 +297,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) | |||
244 | dma_async_issue_pending(chan); | 297 | dma_async_issue_pending(chan); |
245 | } | 298 | } |
246 | dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n", | 299 | dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n", |
247 | __func__, host->data->sg_len, ret, cookie); | 300 | __func__, data->sg_len, ret, cookie); |
248 | 301 | ||
249 | if (!desc) { | 302 | if (!desc) { |
250 | /* DMA failed, fall back to PIO */ | 303 | /* DMA failed, fall back to PIO */ |
@@ -265,18 +318,19 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host) | |||
265 | } | 318 | } |
266 | 319 | ||
267 | dev_dbg(&host->pd->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__, | 320 | dev_dbg(&host->pd->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__, |
268 | desc, cookie, host->data->sg_len); | 321 | desc, cookie, data->sg_len); |
269 | } | 322 | } |
270 | 323 | ||
271 | static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) | 324 | static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) |
272 | { | 325 | { |
273 | struct scatterlist *sg = host->data->sg; | 326 | struct mmc_data *data = host->mrq->data; |
327 | struct scatterlist *sg = data->sg; | ||
274 | struct dma_async_tx_descriptor *desc = NULL; | 328 | struct dma_async_tx_descriptor *desc = NULL; |
275 | struct dma_chan *chan = host->chan_tx; | 329 | struct dma_chan *chan = host->chan_tx; |
276 | dma_cookie_t cookie = -EINVAL; | 330 | dma_cookie_t cookie = -EINVAL; |
277 | int ret; | 331 | int ret; |
278 | 332 | ||
279 | ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len, | 333 | ret = dma_map_sg(chan->device->dev, sg, data->sg_len, |
280 | DMA_TO_DEVICE); | 334 | DMA_TO_DEVICE); |
281 | if (ret > 0) { | 335 | if (ret > 0) { |
282 | host->dma_active = true; | 336 | host->dma_active = true; |
@@ -292,7 +346,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) | |||
292 | dma_async_issue_pending(chan); | 346 | dma_async_issue_pending(chan); |
293 | } | 347 | } |
294 | dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n", | 348 | dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n", |
295 | __func__, host->data->sg_len, ret, cookie); | 349 | __func__, data->sg_len, ret, cookie); |
296 | 350 | ||
297 | if (!desc) { | 351 | if (!desc) { |
298 | /* DMA failed, fall back to PIO */ | 352 | /* DMA failed, fall back to PIO */ |
@@ -399,7 +453,7 @@ static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk) | |||
399 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK); | 453 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK); |
400 | else | 454 | else |
401 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR & | 455 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR & |
402 | (ilog2(__rounddown_pow_of_two(host->clk / clk)) << 16)); | 456 | ((fls(host->clk / clk) - 1) << 16)); |
403 | 457 | ||
404 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); | 458 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); |
405 | } | 459 | } |
@@ -421,7 +475,7 @@ static void sh_mmcif_sync_reset(struct sh_mmcif_host *host) | |||
421 | static int sh_mmcif_error_manage(struct sh_mmcif_host *host) | 475 | static int sh_mmcif_error_manage(struct sh_mmcif_host *host) |
422 | { | 476 | { |
423 | u32 state1, state2; | 477 | u32 state1, state2; |
424 | int ret, timeout = 10000000; | 478 | int ret, timeout; |
425 | 479 | ||
426 | host->sd_error = false; | 480 | host->sd_error = false; |
427 | 481 | ||
@@ -433,155 +487,212 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host) | |||
433 | if (state1 & STS1_CMDSEQ) { | 487 | if (state1 & STS1_CMDSEQ) { |
434 | sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK); | 488 | sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK); |
435 | sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, ~CMD_CTRL_BREAK); | 489 | sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, ~CMD_CTRL_BREAK); |
436 | while (1) { | 490 | for (timeout = 10000000; timeout; timeout--) { |
437 | timeout--; | ||
438 | if (timeout < 0) { | ||
439 | dev_err(&host->pd->dev, | ||
440 | "Forceed end of command sequence timeout err\n"); | ||
441 | return -EIO; | ||
442 | } | ||
443 | if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1) | 491 | if (!(sh_mmcif_readl(host->addr, MMCIF_CE_HOST_STS1) |
444 | & STS1_CMDSEQ)) | 492 | & STS1_CMDSEQ)) |
445 | break; | 493 | break; |
446 | mdelay(1); | 494 | mdelay(1); |
447 | } | 495 | } |
496 | if (!timeout) { | ||
497 | dev_err(&host->pd->dev, | ||
498 | "Forced end of command sequence timeout err\n"); | ||
499 | return -EIO; | ||
500 | } | ||
448 | sh_mmcif_sync_reset(host); | 501 | sh_mmcif_sync_reset(host); |
449 | dev_dbg(&host->pd->dev, "Forced end of command sequence\n"); | 502 | dev_dbg(&host->pd->dev, "Forced end of command sequence\n"); |
450 | return -EIO; | 503 | return -EIO; |
451 | } | 504 | } |
452 | 505 | ||
453 | if (state2 & STS2_CRC_ERR) { | 506 | if (state2 & STS2_CRC_ERR) { |
454 | dev_dbg(&host->pd->dev, ": Happened CRC error\n"); | 507 | dev_dbg(&host->pd->dev, ": CRC error\n"); |
455 | ret = -EIO; | 508 | ret = -EIO; |
456 | } else if (state2 & STS2_TIMEOUT_ERR) { | 509 | } else if (state2 & STS2_TIMEOUT_ERR) { |
457 | dev_dbg(&host->pd->dev, ": Happened Timeout error\n"); | 510 | dev_dbg(&host->pd->dev, ": Timeout\n"); |
458 | ret = -ETIMEDOUT; | 511 | ret = -ETIMEDOUT; |
459 | } else { | 512 | } else { |
460 | dev_dbg(&host->pd->dev, ": Happened End/Index error\n"); | 513 | dev_dbg(&host->pd->dev, ": End/Index error\n"); |
461 | ret = -EIO; | 514 | ret = -EIO; |
462 | } | 515 | } |
463 | return ret; | 516 | return ret; |
464 | } | 517 | } |
465 | 518 | ||
466 | static int sh_mmcif_single_read(struct sh_mmcif_host *host, | 519 | static bool sh_mmcif_next_block(struct sh_mmcif_host *host, u32 *p) |
467 | struct mmc_request *mrq) | ||
468 | { | 520 | { |
469 | struct mmc_data *data = mrq->data; | 521 | struct mmc_data *data = host->mrq->data; |
470 | long time; | 522 | |
471 | u32 blocksize, i, *p = sg_virt(data->sg); | 523 | host->sg_blkidx += host->blocksize; |
524 | |||
525 | /* data->sg->length must be a multiple of host->blocksize? */ | ||
526 | BUG_ON(host->sg_blkidx > data->sg->length); | ||
527 | |||
528 | if (host->sg_blkidx == data->sg->length) { | ||
529 | host->sg_blkidx = 0; | ||
530 | if (++host->sg_idx < data->sg_len) | ||
531 | host->pio_ptr = sg_virt(++data->sg); | ||
532 | } else { | ||
533 | host->pio_ptr = p; | ||
534 | } | ||
535 | |||
536 | if (host->sg_idx == data->sg_len) | ||
537 | return false; | ||
538 | |||
539 | return true; | ||
540 | } | ||
541 | |||
542 | static void sh_mmcif_single_read(struct sh_mmcif_host *host, | ||
543 | struct mmc_request *mrq) | ||
544 | { | ||
545 | host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & | ||
546 | BLOCK_SIZE_MASK) + 3; | ||
547 | |||
548 | host->wait_for = MMCIF_WAIT_FOR_READ; | ||
549 | schedule_delayed_work(&host->timeout_work, host->timeout); | ||
472 | 550 | ||
473 | /* buf read enable */ | 551 | /* buf read enable */ |
474 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); | 552 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); |
475 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, | 553 | } |
476 | host->timeout); | 554 | |
477 | if (time <= 0 || host->sd_error) | 555 | static bool sh_mmcif_read_block(struct sh_mmcif_host *host) |
478 | return sh_mmcif_error_manage(host); | 556 | { |
479 | 557 | struct mmc_data *data = host->mrq->data; | |
480 | blocksize = (BLOCK_SIZE_MASK & | 558 | u32 *p = sg_virt(data->sg); |
481 | sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; | 559 | int i; |
482 | for (i = 0; i < blocksize / 4; i++) | 560 | |
561 | if (host->sd_error) { | ||
562 | data->error = sh_mmcif_error_manage(host); | ||
563 | return false; | ||
564 | } | ||
565 | |||
566 | for (i = 0; i < host->blocksize / 4; i++) | ||
483 | *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA); | 567 | *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA); |
484 | 568 | ||
485 | /* buffer read end */ | 569 | /* buffer read end */ |
486 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); | 570 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); |
487 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, | 571 | host->wait_for = MMCIF_WAIT_FOR_READ_END; |
488 | host->timeout); | ||
489 | if (time <= 0 || host->sd_error) | ||
490 | return sh_mmcif_error_manage(host); | ||
491 | 572 | ||
492 | return 0; | 573 | return true; |
493 | } | 574 | } |
494 | 575 | ||
495 | static int sh_mmcif_multi_read(struct sh_mmcif_host *host, | 576 | static void sh_mmcif_multi_read(struct sh_mmcif_host *host, |
496 | struct mmc_request *mrq) | 577 | struct mmc_request *mrq) |
497 | { | 578 | { |
498 | struct mmc_data *data = mrq->data; | 579 | struct mmc_data *data = mrq->data; |
499 | long time; | 580 | |
500 | u32 blocksize, i, j, sec, *p; | 581 | if (!data->sg_len || !data->sg->length) |
501 | 582 | return; | |
502 | blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr, | 583 | |
503 | MMCIF_CE_BLOCK_SET); | 584 | host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & |
504 | for (j = 0; j < data->sg_len; j++) { | 585 | BLOCK_SIZE_MASK; |
505 | p = sg_virt(data->sg); | 586 | |
506 | for (sec = 0; sec < data->sg->length / blocksize; sec++) { | 587 | host->wait_for = MMCIF_WAIT_FOR_MREAD; |
507 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); | 588 | host->sg_idx = 0; |
508 | /* buf read enable */ | 589 | host->sg_blkidx = 0; |
509 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, | 590 | host->pio_ptr = sg_virt(data->sg); |
510 | host->timeout); | 591 | schedule_delayed_work(&host->timeout_work, host->timeout); |
511 | 592 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); | |
512 | if (time <= 0 || host->sd_error) | 593 | } |
513 | return sh_mmcif_error_manage(host); | 594 | |
514 | 595 | static bool sh_mmcif_mread_block(struct sh_mmcif_host *host) | |
515 | for (i = 0; i < blocksize / 4; i++) | 596 | { |
516 | *p++ = sh_mmcif_readl(host->addr, | 597 | struct mmc_data *data = host->mrq->data; |
517 | MMCIF_CE_DATA); | 598 | u32 *p = host->pio_ptr; |
518 | } | 599 | int i; |
519 | if (j < data->sg_len - 1) | 600 | |
520 | data->sg++; | 601 | if (host->sd_error) { |
602 | data->error = sh_mmcif_error_manage(host); | ||
603 | return false; | ||
521 | } | 604 | } |
522 | return 0; | 605 | |
606 | BUG_ON(!data->sg->length); | ||
607 | |||
608 | for (i = 0; i < host->blocksize / 4; i++) | ||
609 | *p++ = sh_mmcif_readl(host->addr, MMCIF_CE_DATA); | ||
610 | |||
611 | if (!sh_mmcif_next_block(host, p)) | ||
612 | return false; | ||
613 | |||
614 | schedule_delayed_work(&host->timeout_work, host->timeout); | ||
615 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); | ||
616 | |||
617 | return true; | ||
523 | } | 618 | } |
524 | 619 | ||
525 | static int sh_mmcif_single_write(struct sh_mmcif_host *host, | 620 | static void sh_mmcif_single_write(struct sh_mmcif_host *host, |
526 | struct mmc_request *mrq) | 621 | struct mmc_request *mrq) |
527 | { | 622 | { |
528 | struct mmc_data *data = mrq->data; | 623 | host->blocksize = (sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & |
529 | long time; | 624 | BLOCK_SIZE_MASK) + 3; |
530 | u32 blocksize, i, *p = sg_virt(data->sg); | ||
531 | 625 | ||
532 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); | 626 | host->wait_for = MMCIF_WAIT_FOR_WRITE; |
627 | schedule_delayed_work(&host->timeout_work, host->timeout); | ||
533 | 628 | ||
534 | /* buf write enable */ | 629 | /* buf write enable */ |
535 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, | 630 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); |
536 | host->timeout); | 631 | } |
537 | if (time <= 0 || host->sd_error) | 632 | |
538 | return sh_mmcif_error_manage(host); | 633 | static bool sh_mmcif_write_block(struct sh_mmcif_host *host) |
539 | 634 | { | |
540 | blocksize = (BLOCK_SIZE_MASK & | 635 | struct mmc_data *data = host->mrq->data; |
541 | sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET)) + 3; | 636 | u32 *p = sg_virt(data->sg); |
542 | for (i = 0; i < blocksize / 4; i++) | 637 | int i; |
638 | |||
639 | if (host->sd_error) { | ||
640 | data->error = sh_mmcif_error_manage(host); | ||
641 | return false; | ||
642 | } | ||
643 | |||
644 | for (i = 0; i < host->blocksize / 4; i++) | ||
543 | sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++); | 645 | sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++); |
544 | 646 | ||
545 | /* buffer write end */ | 647 | /* buffer write end */ |
546 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); | 648 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); |
649 | host->wait_for = MMCIF_WAIT_FOR_WRITE_END; | ||
547 | 650 | ||
548 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, | 651 | return true; |
549 | host->timeout); | ||
550 | if (time <= 0 || host->sd_error) | ||
551 | return sh_mmcif_error_manage(host); | ||
552 | |||
553 | return 0; | ||
554 | } | 652 | } |
555 | 653 | ||
556 | static int sh_mmcif_multi_write(struct sh_mmcif_host *host, | 654 | static void sh_mmcif_multi_write(struct sh_mmcif_host *host, |
557 | struct mmc_request *mrq) | 655 | struct mmc_request *mrq) |
558 | { | 656 | { |
559 | struct mmc_data *data = mrq->data; | 657 | struct mmc_data *data = mrq->data; |
560 | long time; | ||
561 | u32 i, sec, j, blocksize, *p; | ||
562 | 658 | ||
563 | blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host->addr, | 659 | if (!data->sg_len || !data->sg->length) |
564 | MMCIF_CE_BLOCK_SET); | 660 | return; |
565 | 661 | ||
566 | for (j = 0; j < data->sg_len; j++) { | 662 | host->blocksize = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET) & |
567 | p = sg_virt(data->sg); | 663 | BLOCK_SIZE_MASK; |
568 | for (sec = 0; sec < data->sg->length / blocksize; sec++) { | ||
569 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); | ||
570 | /* buf write enable*/ | ||
571 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, | ||
572 | host->timeout); | ||
573 | 664 | ||
574 | if (time <= 0 || host->sd_error) | 665 | host->wait_for = MMCIF_WAIT_FOR_MWRITE; |
575 | return sh_mmcif_error_manage(host); | 666 | host->sg_idx = 0; |
667 | host->sg_blkidx = 0; | ||
668 | host->pio_ptr = sg_virt(data->sg); | ||
669 | schedule_delayed_work(&host->timeout_work, host->timeout); | ||
670 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); | ||
671 | } | ||
576 | 672 | ||
577 | for (i = 0; i < blocksize / 4; i++) | 673 | static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host) |
578 | sh_mmcif_writel(host->addr, | 674 | { |
579 | MMCIF_CE_DATA, *p++); | 675 | struct mmc_data *data = host->mrq->data; |
580 | } | 676 | u32 *p = host->pio_ptr; |
581 | if (j < data->sg_len - 1) | 677 | int i; |
582 | data->sg++; | 678 | |
679 | if (host->sd_error) { | ||
680 | data->error = sh_mmcif_error_manage(host); | ||
681 | return false; | ||
583 | } | 682 | } |
584 | return 0; | 683 | |
684 | BUG_ON(!data->sg->length); | ||
685 | |||
686 | for (i = 0; i < host->blocksize / 4; i++) | ||
687 | sh_mmcif_writel(host->addr, MMCIF_CE_DATA, *p++); | ||
688 | |||
689 | if (!sh_mmcif_next_block(host, p)) | ||
690 | return false; | ||
691 | |||
692 | schedule_delayed_work(&host->timeout_work, host->timeout); | ||
693 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); | ||
694 | |||
695 | return true; | ||
585 | } | 696 | } |
586 | 697 | ||
587 | static void sh_mmcif_get_response(struct sh_mmcif_host *host, | 698 | static void sh_mmcif_get_response(struct sh_mmcif_host *host, |
@@ -603,8 +714,11 @@ static void sh_mmcif_get_cmd12response(struct sh_mmcif_host *host, | |||
603 | } | 714 | } |
604 | 715 | ||
605 | static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, | 716 | static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, |
606 | struct mmc_request *mrq, struct mmc_command *cmd, u32 opc) | 717 | struct mmc_request *mrq) |
607 | { | 718 | { |
719 | struct mmc_data *data = mrq->data; | ||
720 | struct mmc_command *cmd = mrq->cmd; | ||
721 | u32 opc = cmd->opcode; | ||
608 | u32 tmp = 0; | 722 | u32 tmp = 0; |
609 | 723 | ||
610 | /* Response Type check */ | 724 | /* Response Type check */ |
@@ -636,7 +750,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, | |||
636 | break; | 750 | break; |
637 | } | 751 | } |
638 | /* WDAT / DATW */ | 752 | /* WDAT / DATW */ |
639 | if (host->data) { | 753 | if (data) { |
640 | tmp |= CMD_SET_WDAT; | 754 | tmp |= CMD_SET_WDAT; |
641 | switch (host->bus_width) { | 755 | switch (host->bus_width) { |
642 | case MMC_BUS_WIDTH_1: | 756 | case MMC_BUS_WIDTH_1: |
@@ -660,7 +774,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, | |||
660 | if (opc == MMC_READ_MULTIPLE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) { | 774 | if (opc == MMC_READ_MULTIPLE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) { |
661 | tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN; | 775 | tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN; |
662 | sh_mmcif_bitset(host, MMCIF_CE_BLOCK_SET, | 776 | sh_mmcif_bitset(host, MMCIF_CE_BLOCK_SET, |
663 | mrq->data->blocks << 16); | 777 | data->blocks << 16); |
664 | } | 778 | } |
665 | /* RIDXC[1:0] check bits */ | 779 | /* RIDXC[1:0] check bits */ |
666 | if (opc == MMC_SEND_OP_COND || opc == MMC_ALL_SEND_CID || | 780 | if (opc == MMC_SEND_OP_COND || opc == MMC_ALL_SEND_CID || |
@@ -674,68 +788,60 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, | |||
674 | opc == MMC_SEND_CSD || opc == MMC_SEND_CID) | 788 | opc == MMC_SEND_CSD || opc == MMC_SEND_CID) |
675 | tmp |= CMD_SET_CRC7C_INTERNAL; | 789 | tmp |= CMD_SET_CRC7C_INTERNAL; |
676 | 790 | ||
677 | return opc = ((opc << 24) | tmp); | 791 | return (opc << 24) | tmp; |
678 | } | 792 | } |
679 | 793 | ||
680 | static int sh_mmcif_data_trans(struct sh_mmcif_host *host, | 794 | static int sh_mmcif_data_trans(struct sh_mmcif_host *host, |
681 | struct mmc_request *mrq, u32 opc) | 795 | struct mmc_request *mrq, u32 opc) |
682 | { | 796 | { |
683 | int ret; | ||
684 | |||
685 | switch (opc) { | 797 | switch (opc) { |
686 | case MMC_READ_MULTIPLE_BLOCK: | 798 | case MMC_READ_MULTIPLE_BLOCK: |
687 | ret = sh_mmcif_multi_read(host, mrq); | 799 | sh_mmcif_multi_read(host, mrq); |
688 | break; | 800 | return 0; |
689 | case MMC_WRITE_MULTIPLE_BLOCK: | 801 | case MMC_WRITE_MULTIPLE_BLOCK: |
690 | ret = sh_mmcif_multi_write(host, mrq); | 802 | sh_mmcif_multi_write(host, mrq); |
691 | break; | 803 | return 0; |
692 | case MMC_WRITE_BLOCK: | 804 | case MMC_WRITE_BLOCK: |
693 | ret = sh_mmcif_single_write(host, mrq); | 805 | sh_mmcif_single_write(host, mrq); |
694 | break; | 806 | return 0; |
695 | case MMC_READ_SINGLE_BLOCK: | 807 | case MMC_READ_SINGLE_BLOCK: |
696 | case MMC_SEND_EXT_CSD: | 808 | case MMC_SEND_EXT_CSD: |
697 | ret = sh_mmcif_single_read(host, mrq); | 809 | sh_mmcif_single_read(host, mrq); |
698 | break; | 810 | return 0; |
699 | default: | 811 | default: |
700 | dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc); | 812 | dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc); |
701 | ret = -EINVAL; | 813 | return -EINVAL; |
702 | break; | ||
703 | } | 814 | } |
704 | return ret; | ||
705 | } | 815 | } |
706 | 816 | ||
707 | static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, | 817 | static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, |
708 | struct mmc_request *mrq, struct mmc_command *cmd) | 818 | struct mmc_request *mrq) |
709 | { | 819 | { |
710 | long time; | 820 | struct mmc_command *cmd = mrq->cmd; |
711 | int ret = 0, mask = 0; | ||
712 | u32 opc = cmd->opcode; | 821 | u32 opc = cmd->opcode; |
822 | u32 mask; | ||
713 | 823 | ||
714 | switch (opc) { | 824 | switch (opc) { |
715 | /* respons busy check */ | 825 | /* response busy check */ |
716 | case MMC_SWITCH: | 826 | case MMC_SWITCH: |
717 | case MMC_STOP_TRANSMISSION: | 827 | case MMC_STOP_TRANSMISSION: |
718 | case MMC_SET_WRITE_PROT: | 828 | case MMC_SET_WRITE_PROT: |
719 | case MMC_CLR_WRITE_PROT: | 829 | case MMC_CLR_WRITE_PROT: |
720 | case MMC_ERASE: | 830 | case MMC_ERASE: |
721 | case MMC_GEN_CMD: | 831 | case MMC_GEN_CMD: |
722 | mask = MASK_MRBSYE; | 832 | mask = MASK_START_CMD | MASK_MRBSYE; |
723 | break; | 833 | break; |
724 | default: | 834 | default: |
725 | mask = MASK_MCRSPE; | 835 | mask = MASK_START_CMD | MASK_MCRSPE; |
726 | break; | 836 | break; |
727 | } | 837 | } |
728 | mask |= MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | | ||
729 | MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | | ||
730 | MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | | ||
731 | MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO; | ||
732 | 838 | ||
733 | if (host->data) { | 839 | if (mrq->data) { |
734 | sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0); | 840 | sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, 0); |
735 | sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, | 841 | sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, |
736 | mrq->data->blksz); | 842 | mrq->data->blksz); |
737 | } | 843 | } |
738 | opc = sh_mmcif_set_cmd(host, mrq, cmd, opc); | 844 | opc = sh_mmcif_set_cmd(host, mrq); |
739 | 845 | ||
740 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0); | 846 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, 0xD80430C0); |
741 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask); | 847 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, mask); |
@@ -744,80 +850,28 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, | |||
744 | /* set cmd */ | 850 | /* set cmd */ |
745 | sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc); | 851 | sh_mmcif_writel(host->addr, MMCIF_CE_CMD_SET, opc); |
746 | 852 | ||
747 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, | 853 | host->wait_for = MMCIF_WAIT_FOR_CMD; |
748 | host->timeout); | 854 | schedule_delayed_work(&host->timeout_work, host->timeout); |
749 | if (time <= 0) { | ||
750 | cmd->error = sh_mmcif_error_manage(host); | ||
751 | return; | ||
752 | } | ||
753 | if (host->sd_error) { | ||
754 | switch (cmd->opcode) { | ||
755 | case MMC_ALL_SEND_CID: | ||
756 | case MMC_SELECT_CARD: | ||
757 | case MMC_APP_CMD: | ||
758 | cmd->error = -ETIMEDOUT; | ||
759 | break; | ||
760 | default: | ||
761 | dev_dbg(&host->pd->dev, "Cmd(d'%d) err\n", | ||
762 | cmd->opcode); | ||
763 | cmd->error = sh_mmcif_error_manage(host); | ||
764 | break; | ||
765 | } | ||
766 | host->sd_error = false; | ||
767 | return; | ||
768 | } | ||
769 | if (!(cmd->flags & MMC_RSP_PRESENT)) { | ||
770 | cmd->error = 0; | ||
771 | return; | ||
772 | } | ||
773 | sh_mmcif_get_response(host, cmd); | ||
774 | if (host->data) { | ||
775 | if (!host->dma_active) { | ||
776 | ret = sh_mmcif_data_trans(host, mrq, cmd->opcode); | ||
777 | } else { | ||
778 | long time = | ||
779 | wait_for_completion_interruptible_timeout(&host->dma_complete, | ||
780 | host->timeout); | ||
781 | if (!time) | ||
782 | ret = -ETIMEDOUT; | ||
783 | else if (time < 0) | ||
784 | ret = time; | ||
785 | sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, | ||
786 | BUF_ACC_DMAREN | BUF_ACC_DMAWEN); | ||
787 | host->dma_active = false; | ||
788 | } | ||
789 | if (ret < 0) | ||
790 | mrq->data->bytes_xfered = 0; | ||
791 | else | ||
792 | mrq->data->bytes_xfered = | ||
793 | mrq->data->blocks * mrq->data->blksz; | ||
794 | } | ||
795 | cmd->error = ret; | ||
796 | } | 855 | } |
797 | 856 | ||
798 | static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, | 857 | static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, |
799 | struct mmc_request *mrq, struct mmc_command *cmd) | 858 | struct mmc_request *mrq) |
800 | { | 859 | { |
801 | long time; | 860 | switch (mrq->cmd->opcode) { |
802 | 861 | case MMC_READ_MULTIPLE_BLOCK: | |
803 | if (mrq->cmd->opcode == MMC_READ_MULTIPLE_BLOCK) | ||
804 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE); | 862 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE); |
805 | else if (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) | 863 | break; |
864 | case MMC_WRITE_MULTIPLE_BLOCK: | ||
806 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE); | 865 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE); |
807 | else { | 866 | break; |
867 | default: | ||
808 | dev_err(&host->pd->dev, "unsupported stop cmd\n"); | 868 | dev_err(&host->pd->dev, "unsupported stop cmd\n"); |
809 | cmd->error = sh_mmcif_error_manage(host); | 869 | mrq->stop->error = sh_mmcif_error_manage(host); |
810 | return; | 870 | return; |
811 | } | 871 | } |
812 | 872 | ||
813 | time = wait_for_completion_interruptible_timeout(&host->intr_wait, | 873 | host->wait_for = MMCIF_WAIT_FOR_STOP; |
814 | host->timeout); | 874 | schedule_delayed_work(&host->timeout_work, host->timeout); |
815 | if (time <= 0 || host->sd_error) { | ||
816 | cmd->error = sh_mmcif_error_manage(host); | ||
817 | return; | ||
818 | } | ||
819 | sh_mmcif_get_cmd12response(host, cmd); | ||
820 | cmd->error = 0; | ||
821 | } | 875 | } |
822 | 876 | ||
823 | static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) | 877 | static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) |
@@ -856,23 +910,10 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
856 | default: | 910 | default: |
857 | break; | 911 | break; |
858 | } | 912 | } |
859 | host->data = mrq->data; | ||
860 | if (mrq->data) { | ||
861 | if (mrq->data->flags & MMC_DATA_READ) { | ||
862 | if (host->chan_rx) | ||
863 | sh_mmcif_start_dma_rx(host); | ||
864 | } else { | ||
865 | if (host->chan_tx) | ||
866 | sh_mmcif_start_dma_tx(host); | ||
867 | } | ||
868 | } | ||
869 | sh_mmcif_start_cmd(host, mrq, mrq->cmd); | ||
870 | host->data = NULL; | ||
871 | 913 | ||
872 | if (!mrq->cmd->error && mrq->stop) | 914 | host->mrq = mrq; |
873 | sh_mmcif_stop_cmd(host, mrq, mrq->stop); | 915 | |
874 | host->state = STATE_IDLE; | 916 | sh_mmcif_start_cmd(host, mrq); |
875 | mmc_request_done(mmc, mrq); | ||
876 | } | 917 | } |
877 | 918 | ||
878 | static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | 919 | static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
@@ -947,9 +988,156 @@ static struct mmc_host_ops sh_mmcif_ops = { | |||
947 | .get_cd = sh_mmcif_get_cd, | 988 | .get_cd = sh_mmcif_get_cd, |
948 | }; | 989 | }; |
949 | 990 | ||
950 | static void sh_mmcif_detect(struct mmc_host *mmc) | 991 | static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host) |
951 | { | 992 | { |
952 | mmc_detect_change(mmc, 0); | 993 | struct mmc_command *cmd = host->mrq->cmd; |
994 | struct mmc_data *data = host->mrq->data; | ||
995 | long time; | ||
996 | |||
997 | if (host->sd_error) { | ||
998 | switch (cmd->opcode) { | ||
999 | case MMC_ALL_SEND_CID: | ||
1000 | case MMC_SELECT_CARD: | ||
1001 | case MMC_APP_CMD: | ||
1002 | cmd->error = -ETIMEDOUT; | ||
1003 | host->sd_error = false; | ||
1004 | break; | ||
1005 | default: | ||
1006 | cmd->error = sh_mmcif_error_manage(host); | ||
1007 | dev_dbg(&host->pd->dev, "Cmd(d'%d) error %d\n", | ||
1008 | cmd->opcode, cmd->error); | ||
1009 | break; | ||
1010 | } | ||
1011 | return false; | ||
1012 | } | ||
1013 | if (!(cmd->flags & MMC_RSP_PRESENT)) { | ||
1014 | cmd->error = 0; | ||
1015 | return false; | ||
1016 | } | ||
1017 | |||
1018 | sh_mmcif_get_response(host, cmd); | ||
1019 | |||
1020 | if (!data) | ||
1021 | return false; | ||
1022 | |||
1023 | if (data->flags & MMC_DATA_READ) { | ||
1024 | if (host->chan_rx) | ||
1025 | sh_mmcif_start_dma_rx(host); | ||
1026 | } else { | ||
1027 | if (host->chan_tx) | ||
1028 | sh_mmcif_start_dma_tx(host); | ||
1029 | } | ||
1030 | |||
1031 | if (!host->dma_active) { | ||
1032 | data->error = sh_mmcif_data_trans(host, host->mrq, cmd->opcode); | ||
1033 | if (!data->error) | ||
1034 | return true; | ||
1035 | return false; | ||
1036 | } | ||
1037 | |||
1038 | /* Running in the IRQ thread, can sleep */ | ||
1039 | time = wait_for_completion_interruptible_timeout(&host->dma_complete, | ||
1040 | host->timeout); | ||
1041 | if (host->sd_error) { | ||
1042 | dev_err(host->mmc->parent, | ||
1043 | "Error IRQ while waiting for DMA completion!\n"); | ||
1044 | /* Woken up by an error IRQ: abort DMA */ | ||
1045 | if (data->flags & MMC_DATA_READ) | ||
1046 | dmaengine_terminate_all(host->chan_rx); | ||
1047 | else | ||
1048 | dmaengine_terminate_all(host->chan_tx); | ||
1049 | data->error = sh_mmcif_error_manage(host); | ||
1050 | } else if (!time) { | ||
1051 | data->error = -ETIMEDOUT; | ||
1052 | } else if (time < 0) { | ||
1053 | data->error = time; | ||
1054 | } | ||
1055 | sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC, | ||
1056 | BUF_ACC_DMAREN | BUF_ACC_DMAWEN); | ||
1057 | host->dma_active = false; | ||
1058 | |||
1059 | if (data->error) | ||
1060 | data->bytes_xfered = 0; | ||
1061 | |||
1062 | return false; | ||
1063 | } | ||
1064 | |||
1065 | static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) | ||
1066 | { | ||
1067 | struct sh_mmcif_host *host = dev_id; | ||
1068 | struct mmc_request *mrq = host->mrq; | ||
1069 | struct mmc_data *data = mrq->data; | ||
1070 | |||
1071 | cancel_delayed_work_sync(&host->timeout_work); | ||
1072 | |||
1073 | /* | ||
1074 | * All handlers return true, if processing continues, and false, if the | ||
1075 | * request has to be completed - successfully or not | ||
1076 | */ | ||
1077 | switch (host->wait_for) { | ||
1078 | case MMCIF_WAIT_FOR_REQUEST: | ||
1079 | /* We're too late, the timeout has already kicked in */ | ||
1080 | return IRQ_HANDLED; | ||
1081 | case MMCIF_WAIT_FOR_CMD: | ||
1082 | if (sh_mmcif_end_cmd(host)) | ||
1083 | /* Wait for data */ | ||
1084 | return IRQ_HANDLED; | ||
1085 | break; | ||
1086 | case MMCIF_WAIT_FOR_MREAD: | ||
1087 | if (sh_mmcif_mread_block(host)) | ||
1088 | /* Wait for more data */ | ||
1089 | return IRQ_HANDLED; | ||
1090 | break; | ||
1091 | case MMCIF_WAIT_FOR_READ: | ||
1092 | if (sh_mmcif_read_block(host)) | ||
1093 | /* Wait for data end */ | ||
1094 | return IRQ_HANDLED; | ||
1095 | break; | ||
1096 | case MMCIF_WAIT_FOR_MWRITE: | ||
1097 | if (sh_mmcif_mwrite_block(host)) | ||
1098 | /* Wait data to write */ | ||
1099 | return IRQ_HANDLED; | ||
1100 | break; | ||
1101 | case MMCIF_WAIT_FOR_WRITE: | ||
1102 | if (sh_mmcif_write_block(host)) | ||
1103 | /* Wait for data end */ | ||
1104 | return IRQ_HANDLED; | ||
1105 | break; | ||
1106 | case MMCIF_WAIT_FOR_STOP: | ||
1107 | if (host->sd_error) { | ||
1108 | mrq->stop->error = sh_mmcif_error_manage(host); | ||
1109 | break; | ||
1110 | } | ||
1111 | sh_mmcif_get_cmd12response(host, mrq->stop); | ||
1112 | mrq->stop->error = 0; | ||
1113 | break; | ||
1114 | case MMCIF_WAIT_FOR_READ_END: | ||
1115 | case MMCIF_WAIT_FOR_WRITE_END: | ||
1116 | if (host->sd_error) | ||
1117 | data->error = sh_mmcif_error_manage(host); | ||
1118 | break; | ||
1119 | default: | ||
1120 | BUG(); | ||
1121 | } | ||
1122 | |||
1123 | if (host->wait_for != MMCIF_WAIT_FOR_STOP) { | ||
1124 | if (!mrq->cmd->error && data && !data->error) | ||
1125 | data->bytes_xfered = | ||
1126 | data->blocks * data->blksz; | ||
1127 | |||
1128 | if (mrq->stop && !mrq->cmd->error && (!data || !data->error)) { | ||
1129 | sh_mmcif_stop_cmd(host, mrq); | ||
1130 | if (!mrq->stop->error) | ||
1131 | return IRQ_HANDLED; | ||
1132 | } | ||
1133 | } | ||
1134 | |||
1135 | host->wait_for = MMCIF_WAIT_FOR_REQUEST; | ||
1136 | host->state = STATE_IDLE; | ||
1137 | host->mrq = NULL; | ||
1138 | mmc_request_done(host->mmc, mrq); | ||
1139 | |||
1140 | return IRQ_HANDLED; | ||
953 | } | 1141 | } |
954 | 1142 | ||
955 | static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | 1143 | static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) |
@@ -960,7 +1148,12 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | |||
960 | 1148 | ||
961 | state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); | 1149 | state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); |
962 | 1150 | ||
963 | if (state & INT_RBSYE) { | 1151 | if (state & INT_ERR_STS) { |
1152 | /* error interrupts - process first */ | ||
1153 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); | ||
1154 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state); | ||
1155 | err = 1; | ||
1156 | } else if (state & INT_RBSYE) { | ||
964 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, | 1157 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, |
965 | ~(INT_RBSYE | INT_CRSPE)); | 1158 | ~(INT_RBSYE | INT_CRSPE)); |
966 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE); | 1159 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE); |
@@ -988,11 +1181,6 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | |||
988 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, | 1181 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, |
989 | ~(INT_CMD12RBE | INT_CMD12CRE)); | 1182 | ~(INT_CMD12RBE | INT_CMD12CRE)); |
990 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE); | 1183 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE); |
991 | } else if (state & INT_ERR_STS) { | ||
992 | /* err interrupts */ | ||
993 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); | ||
994 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state); | ||
995 | err = 1; | ||
996 | } else { | 1184 | } else { |
997 | dev_dbg(&host->pd->dev, "Unsupported interrupt: 0x%x\n", state); | 1185 | dev_dbg(&host->pd->dev, "Unsupported interrupt: 0x%x\n", state); |
998 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); | 1186 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); |
@@ -1003,14 +1191,57 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | |||
1003 | host->sd_error = true; | 1191 | host->sd_error = true; |
1004 | dev_dbg(&host->pd->dev, "int err state = %08x\n", state); | 1192 | dev_dbg(&host->pd->dev, "int err state = %08x\n", state); |
1005 | } | 1193 | } |
1006 | if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) | 1194 | if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) { |
1007 | complete(&host->intr_wait); | 1195 | if (!host->dma_active) |
1008 | else | 1196 | return IRQ_WAKE_THREAD; |
1197 | else if (host->sd_error) | ||
1198 | mmcif_dma_complete(host); | ||
1199 | } else { | ||
1009 | dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state); | 1200 | dev_dbg(&host->pd->dev, "Unexpected IRQ 0x%x\n", state); |
1201 | } | ||
1010 | 1202 | ||
1011 | return IRQ_HANDLED; | 1203 | return IRQ_HANDLED; |
1012 | } | 1204 | } |
1013 | 1205 | ||
1206 | static void mmcif_timeout_work(struct work_struct *work) | ||
1207 | { | ||
1208 | struct delayed_work *d = container_of(work, struct delayed_work, work); | ||
1209 | struct sh_mmcif_host *host = container_of(d, struct sh_mmcif_host, timeout_work); | ||
1210 | struct mmc_request *mrq = host->mrq; | ||
1211 | |||
1212 | if (host->dying) | ||
1213 | /* Don't run after mmc_remove_host() */ | ||
1214 | return; | ||
1215 | |||
1216 | /* | ||
1217 | * Handle races with cancel_delayed_work(), unless | ||
1218 | * cancel_delayed_work_sync() is used | ||
1219 | */ | ||
1220 | switch (host->wait_for) { | ||
1221 | case MMCIF_WAIT_FOR_CMD: | ||
1222 | mrq->cmd->error = sh_mmcif_error_manage(host); | ||
1223 | break; | ||
1224 | case MMCIF_WAIT_FOR_STOP: | ||
1225 | mrq->stop->error = sh_mmcif_error_manage(host); | ||
1226 | break; | ||
1227 | case MMCIF_WAIT_FOR_MREAD: | ||
1228 | case MMCIF_WAIT_FOR_MWRITE: | ||
1229 | case MMCIF_WAIT_FOR_READ: | ||
1230 | case MMCIF_WAIT_FOR_WRITE: | ||
1231 | case MMCIF_WAIT_FOR_READ_END: | ||
1232 | case MMCIF_WAIT_FOR_WRITE_END: | ||
1233 | mrq->data->error = sh_mmcif_error_manage(host); | ||
1234 | break; | ||
1235 | default: | ||
1236 | BUG(); | ||
1237 | } | ||
1238 | |||
1239 | host->state = STATE_IDLE; | ||
1240 | host->wait_for = MMCIF_WAIT_FOR_REQUEST; | ||
1241 | host->mrq = NULL; | ||
1242 | mmc_request_done(host->mmc, mrq); | ||
1243 | } | ||
1244 | |||
1014 | static int __devinit sh_mmcif_probe(struct platform_device *pdev) | 1245 | static int __devinit sh_mmcif_probe(struct platform_device *pdev) |
1015 | { | 1246 | { |
1016 | int ret = 0, irq[2]; | 1247 | int ret = 0, irq[2]; |
@@ -1064,7 +1295,6 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) | |||
1064 | host->clk = clk_get_rate(host->hclk); | 1295 | host->clk = clk_get_rate(host->hclk); |
1065 | host->pd = pdev; | 1296 | host->pd = pdev; |
1066 | 1297 | ||
1067 | init_completion(&host->intr_wait); | ||
1068 | spin_lock_init(&host->lock); | 1298 | spin_lock_init(&host->lock); |
1069 | 1299 | ||
1070 | mmc->ops = &sh_mmcif_ops; | 1300 | mmc->ops = &sh_mmcif_ops; |
@@ -1101,19 +1331,21 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) | |||
1101 | 1331 | ||
1102 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); | 1332 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); |
1103 | 1333 | ||
1104 | ret = request_irq(irq[0], sh_mmcif_intr, 0, "sh_mmc:error", host); | 1334 | ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host); |
1105 | if (ret) { | 1335 | if (ret) { |
1106 | dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n"); | 1336 | dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n"); |
1107 | goto clean_up3; | 1337 | goto clean_up3; |
1108 | } | 1338 | } |
1109 | ret = request_irq(irq[1], sh_mmcif_intr, 0, "sh_mmc:int", host); | 1339 | ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); |
1110 | if (ret) { | 1340 | if (ret) { |
1111 | free_irq(irq[0], host); | 1341 | free_irq(irq[0], host); |
1112 | dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); | 1342 | dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); |
1113 | goto clean_up3; | 1343 | goto clean_up3; |
1114 | } | 1344 | } |
1115 | 1345 | ||
1116 | sh_mmcif_detect(host->mmc); | 1346 | INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); |
1347 | |||
1348 | mmc_detect_change(host->mmc, 0); | ||
1117 | 1349 | ||
1118 | dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); | 1350 | dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); |
1119 | dev_dbg(&pdev->dev, "chip ver H'%04x\n", | 1351 | dev_dbg(&pdev->dev, "chip ver H'%04x\n", |
@@ -1139,11 +1371,19 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev) | |||
1139 | struct sh_mmcif_host *host = platform_get_drvdata(pdev); | 1371 | struct sh_mmcif_host *host = platform_get_drvdata(pdev); |
1140 | int irq[2]; | 1372 | int irq[2]; |
1141 | 1373 | ||
1374 | host->dying = true; | ||
1142 | pm_runtime_get_sync(&pdev->dev); | 1375 | pm_runtime_get_sync(&pdev->dev); |
1143 | 1376 | ||
1144 | mmc_remove_host(host->mmc); | 1377 | mmc_remove_host(host->mmc); |
1145 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); | 1378 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); |
1146 | 1379 | ||
1380 | /* | ||
1381 | * FIXME: cancel_delayed_work(_sync)() and free_irq() race with the | ||
1382 | * mmc_remove_host() call above. But swapping order doesn't help either | ||
1383 | * (a query on the linux-mmc mailing list didn't bring any replies). | ||
1384 | */ | ||
1385 | cancel_delayed_work_sync(&host->timeout_work); | ||
1386 | |||
1147 | if (host->addr) | 1387 | if (host->addr) |
1148 | iounmap(host->addr); | 1388 | iounmap(host->addr); |
1149 | 1389 | ||
@@ -1206,19 +1446,7 @@ static struct platform_driver sh_mmcif_driver = { | |||
1206 | }, | 1446 | }, |
1207 | }; | 1447 | }; |
1208 | 1448 | ||
1209 | static int __init sh_mmcif_init(void) | 1449 | module_platform_driver(sh_mmcif_driver); |
1210 | { | ||
1211 | return platform_driver_register(&sh_mmcif_driver); | ||
1212 | } | ||
1213 | |||
1214 | static void __exit sh_mmcif_exit(void) | ||
1215 | { | ||
1216 | platform_driver_unregister(&sh_mmcif_driver); | ||
1217 | } | ||
1218 | |||
1219 | module_init(sh_mmcif_init); | ||
1220 | module_exit(sh_mmcif_exit); | ||
1221 | |||
1222 | 1450 | ||
1223 | MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver"); | 1451 | MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver"); |
1224 | MODULE_LICENSE("GPL"); | 1452 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index 41ae6466bd83..58da3c44acc5 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c | |||
@@ -282,18 +282,7 @@ static struct platform_driver sh_mobile_sdhi_driver = { | |||
282 | .remove = __devexit_p(sh_mobile_sdhi_remove), | 282 | .remove = __devexit_p(sh_mobile_sdhi_remove), |
283 | }; | 283 | }; |
284 | 284 | ||
285 | static int __init sh_mobile_sdhi_init(void) | 285 | module_platform_driver(sh_mobile_sdhi_driver); |
286 | { | ||
287 | return platform_driver_register(&sh_mobile_sdhi_driver); | ||
288 | } | ||
289 | |||
290 | static void __exit sh_mobile_sdhi_exit(void) | ||
291 | { | ||
292 | platform_driver_unregister(&sh_mobile_sdhi_driver); | ||
293 | } | ||
294 | |||
295 | module_init(sh_mobile_sdhi_init); | ||
296 | module_exit(sh_mobile_sdhi_exit); | ||
297 | 286 | ||
298 | MODULE_DESCRIPTION("SuperH Mobile SDHI driver"); | 287 | MODULE_DESCRIPTION("SuperH Mobile SDHI driver"); |
299 | MODULE_AUTHOR("Magnus Damm"); | 288 | MODULE_AUTHOR("Magnus Damm"); |
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index f70d04664cac..fc00081687b9 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c | |||
@@ -118,7 +118,7 @@ static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg, | |||
118 | unsigned char *buf; | 118 | unsigned char *buf; |
119 | unsigned int pos = 0, val; | 119 | unsigned int pos = 0, val; |
120 | 120 | ||
121 | buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + off; | 121 | buf = kmap_atomic(pg) + off; |
122 | if (host->cmd_flags & DATA_CARRY) { | 122 | if (host->cmd_flags & DATA_CARRY) { |
123 | buf[pos++] = host->bounce_buf_data[0]; | 123 | buf[pos++] = host->bounce_buf_data[0]; |
124 | host->cmd_flags &= ~DATA_CARRY; | 124 | host->cmd_flags &= ~DATA_CARRY; |
@@ -134,7 +134,7 @@ static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg, | |||
134 | } | 134 | } |
135 | buf[pos++] = (val >> 8) & 0xff; | 135 | buf[pos++] = (val >> 8) & 0xff; |
136 | } | 136 | } |
137 | kunmap_atomic(buf - off, KM_BIO_DST_IRQ); | 137 | kunmap_atomic(buf - off); |
138 | } | 138 | } |
139 | 139 | ||
140 | static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg, | 140 | static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg, |
@@ -144,7 +144,7 @@ static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg, | |||
144 | unsigned char *buf; | 144 | unsigned char *buf; |
145 | unsigned int pos = 0, val; | 145 | unsigned int pos = 0, val; |
146 | 146 | ||
147 | buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + off; | 147 | buf = kmap_atomic(pg) + off; |
148 | if (host->cmd_flags & DATA_CARRY) { | 148 | if (host->cmd_flags & DATA_CARRY) { |
149 | val = host->bounce_buf_data[0] | ((buf[pos++] << 8) & 0xff00); | 149 | val = host->bounce_buf_data[0] | ((buf[pos++] << 8) & 0xff00); |
150 | writel(val, sock->addr + SOCK_MMCSD_DATA); | 150 | writel(val, sock->addr + SOCK_MMCSD_DATA); |
@@ -161,7 +161,7 @@ static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg, | |||
161 | val |= (buf[pos++] << 8) & 0xff00; | 161 | val |= (buf[pos++] << 8) & 0xff00; |
162 | writel(val, sock->addr + SOCK_MMCSD_DATA); | 162 | writel(val, sock->addr + SOCK_MMCSD_DATA); |
163 | } | 163 | } |
164 | kunmap_atomic(buf - off, KM_BIO_SRC_IRQ); | 164 | kunmap_atomic(buf - off); |
165 | } | 165 | } |
166 | 166 | ||
167 | static void tifm_sd_transfer_data(struct tifm_sd *host) | 167 | static void tifm_sd_transfer_data(struct tifm_sd *host) |
@@ -212,13 +212,13 @@ static void tifm_sd_copy_page(struct page *dst, unsigned int dst_off, | |||
212 | struct page *src, unsigned int src_off, | 212 | struct page *src, unsigned int src_off, |
213 | unsigned int count) | 213 | unsigned int count) |
214 | { | 214 | { |
215 | unsigned char *src_buf = kmap_atomic(src, KM_BIO_SRC_IRQ) + src_off; | 215 | unsigned char *src_buf = kmap_atomic(src) + src_off; |
216 | unsigned char *dst_buf = kmap_atomic(dst, KM_BIO_DST_IRQ) + dst_off; | 216 | unsigned char *dst_buf = kmap_atomic(dst) + dst_off; |
217 | 217 | ||
218 | memcpy(dst_buf, src_buf, count); | 218 | memcpy(dst_buf, src_buf, count); |
219 | 219 | ||
220 | kunmap_atomic(dst_buf - dst_off, KM_BIO_DST_IRQ); | 220 | kunmap_atomic(dst_buf - dst_off); |
221 | kunmap_atomic(src_buf - src_off, KM_BIO_SRC_IRQ); | 221 | kunmap_atomic(src_buf - src_off); |
222 | } | 222 | } |
223 | 223 | ||
224 | static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data) | 224 | static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data) |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index a4ea10242787..113ce6c9cf32 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
@@ -138,19 +138,7 @@ static struct platform_driver tmio_mmc_driver = { | |||
138 | .resume = tmio_mmc_resume, | 138 | .resume = tmio_mmc_resume, |
139 | }; | 139 | }; |
140 | 140 | ||
141 | 141 | module_platform_driver(tmio_mmc_driver); | |
142 | static int __init tmio_mmc_init(void) | ||
143 | { | ||
144 | return platform_driver_register(&tmio_mmc_driver); | ||
145 | } | ||
146 | |||
147 | static void __exit tmio_mmc_exit(void) | ||
148 | { | ||
149 | platform_driver_unregister(&tmio_mmc_driver); | ||
150 | } | ||
151 | |||
152 | module_init(tmio_mmc_init); | ||
153 | module_exit(tmio_mmc_exit); | ||
154 | 142 | ||
155 | MODULE_DESCRIPTION("Toshiba TMIO SD/MMC driver"); | 143 | MODULE_DESCRIPTION("Toshiba TMIO SD/MMC driver"); |
156 | MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); | 144 | MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); |
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 3020f98218f0..a95e6d901726 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h | |||
@@ -105,13 +105,13 @@ static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, | |||
105 | unsigned long *flags) | 105 | unsigned long *flags) |
106 | { | 106 | { |
107 | local_irq_save(*flags); | 107 | local_irq_save(*flags); |
108 | return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; | 108 | return kmap_atomic(sg_page(sg)) + sg->offset; |
109 | } | 109 | } |
110 | 110 | ||
111 | static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg, | 111 | static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg, |
112 | unsigned long *flags, void *virt) | 112 | unsigned long *flags, void *virt) |
113 | { | 113 | { |
114 | kunmap_atomic(virt - sg->offset, KM_BIO_SRC_IRQ); | 114 | kunmap_atomic(virt - sg->offset); |
115 | local_irq_restore(*flags); | 115 | local_irq_restore(*flags); |
116 | } | 116 | } |
117 | 117 | ||
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 4208b3958069..abad01b37cfb 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
@@ -800,8 +800,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
800 | } else if (ios->power_mode != MMC_POWER_UP) { | 800 | } else if (ios->power_mode != MMC_POWER_UP) { |
801 | if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) | 801 | if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) |
802 | host->set_pwr(host->pdev, 0); | 802 | host->set_pwr(host->pdev, 0); |
803 | if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && | 803 | if (pdata->power) { |
804 | pdata->power) { | ||
805 | pdata->power = false; | 804 | pdata->power = false; |
806 | pm_runtime_put(&host->pdev->dev); | 805 | pm_runtime_put(&host->pdev->dev); |
807 | } | 806 | } |
@@ -915,6 +914,23 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
915 | if (ret < 0) | 914 | if (ret < 0) |
916 | goto pm_disable; | 915 | goto pm_disable; |
917 | 916 | ||
917 | /* | ||
918 | * There are 4 different scenarios for the card detection: | ||
919 | * 1) an external gpio irq handles the cd (best for power savings) | ||
920 | * 2) internal sdhi irq handles the cd | ||
921 | * 3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL | ||
922 | * 4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE | ||
923 | * | ||
924 | * While we increment the rtpm counter for all scenarios when the mmc | ||
925 | * core activates us by calling an appropriate set_ios(), we must | ||
926 | * additionally ensure that in case 2) the tmio mmc hardware stays | ||
927 | * powered on during runtime for the card detection to work. | ||
928 | */ | ||
929 | if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD | ||
930 | || mmc->caps & MMC_CAP_NEEDS_POLL | ||
931 | || mmc->caps & MMC_CAP_NONREMOVABLE)) | ||
932 | pm_runtime_get_noresume(&pdev->dev); | ||
933 | |||
918 | tmio_mmc_clk_stop(_host); | 934 | tmio_mmc_clk_stop(_host); |
919 | tmio_mmc_reset(_host); | 935 | tmio_mmc_reset(_host); |
920 | 936 | ||
@@ -933,12 +949,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
933 | /* See if we also get DMA */ | 949 | /* See if we also get DMA */ |
934 | tmio_mmc_request_dma(_host, pdata); | 950 | tmio_mmc_request_dma(_host, pdata); |
935 | 951 | ||
936 | /* We have to keep the device powered for its card detection to work */ | ||
937 | if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD)) { | ||
938 | pdata->power = true; | ||
939 | pm_runtime_get_noresume(&pdev->dev); | ||
940 | } | ||
941 | |||
942 | mmc_add_host(mmc); | 952 | mmc_add_host(mmc); |
943 | 953 | ||
944 | /* Unmask the IRQs we want to know about */ | 954 | /* Unmask the IRQs we want to know about */ |
@@ -974,7 +984,9 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) | |||
974 | * the controller, the runtime PM is suspended and pdata->power == false, | 984 | * the controller, the runtime PM is suspended and pdata->power == false, |
975 | * so, our .runtime_resume() will not try to detect a card in the slot. | 985 | * so, our .runtime_resume() will not try to detect a card in the slot. |
976 | */ | 986 | */ |
977 | if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD) | 987 | if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD |
988 | || host->mmc->caps & MMC_CAP_NEEDS_POLL | ||
989 | || host->mmc->caps & MMC_CAP_NONREMOVABLE) | ||
978 | pm_runtime_get_sync(&pdev->dev); | 990 | pm_runtime_get_sync(&pdev->dev); |
979 | 991 | ||
980 | mmc_remove_host(host->mmc); | 992 | mmc_remove_host(host->mmc); |