diff options
Diffstat (limited to 'drivers')
29 files changed, 1249 insertions, 337 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 29d5d988a51c..7b5424f398ac 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
| @@ -1959,6 +1959,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 1959 | struct mmc_card *card = md->queue.card; | 1959 | struct mmc_card *card = md->queue.card; |
| 1960 | struct mmc_host *host = card->host; | 1960 | struct mmc_host *host = card->host; |
| 1961 | unsigned long flags; | 1961 | unsigned long flags; |
| 1962 | unsigned int cmd_flags = req ? req->cmd_flags : 0; | ||
| 1962 | 1963 | ||
| 1963 | if (req && !mq->mqrq_prev->req) | 1964 | if (req && !mq->mqrq_prev->req) |
| 1964 | /* claim host only for the first request */ | 1965 | /* claim host only for the first request */ |
| @@ -1974,7 +1975,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 1974 | } | 1975 | } |
| 1975 | 1976 | ||
| 1976 | mq->flags &= ~MMC_QUEUE_NEW_REQUEST; | 1977 | mq->flags &= ~MMC_QUEUE_NEW_REQUEST; |
| 1977 | if (req && req->cmd_flags & REQ_DISCARD) { | 1978 | if (cmd_flags & REQ_DISCARD) { |
| 1978 | /* complete ongoing async transfer before issuing discard */ | 1979 | /* complete ongoing async transfer before issuing discard */ |
| 1979 | if (card->host->areq) | 1980 | if (card->host->areq) |
| 1980 | mmc_blk_issue_rw_rq(mq, NULL); | 1981 | mmc_blk_issue_rw_rq(mq, NULL); |
| @@ -1983,7 +1984,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 1983 | ret = mmc_blk_issue_secdiscard_rq(mq, req); | 1984 | ret = mmc_blk_issue_secdiscard_rq(mq, req); |
| 1984 | else | 1985 | else |
| 1985 | ret = mmc_blk_issue_discard_rq(mq, req); | 1986 | ret = mmc_blk_issue_discard_rq(mq, req); |
| 1986 | } else if (req && req->cmd_flags & REQ_FLUSH) { | 1987 | } else if (cmd_flags & REQ_FLUSH) { |
| 1987 | /* complete ongoing async transfer before issuing flush */ | 1988 | /* complete ongoing async transfer before issuing flush */ |
| 1988 | if (card->host->areq) | 1989 | if (card->host->areq) |
| 1989 | mmc_blk_issue_rw_rq(mq, NULL); | 1990 | mmc_blk_issue_rw_rq(mq, NULL); |
| @@ -1999,7 +2000,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 1999 | 2000 | ||
| 2000 | out: | 2001 | out: |
| 2001 | if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || | 2002 | if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || |
| 2002 | (req && (req->cmd_flags & MMC_REQ_SPECIAL_MASK))) | 2003 | (cmd_flags & MMC_REQ_SPECIAL_MASK)) |
| 2003 | /* | 2004 | /* |
| 2004 | * Release host when there are no more requests | 2005 | * Release host when there are no more requests |
| 2005 | * and after special request(discard, flush) is done. | 2006 | * and after special request(discard, flush) is done. |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 57a2b403bf8e..098374b1ab2b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -2460,7 +2460,8 @@ void mmc_rescan(struct work_struct *work) | |||
| 2460 | */ | 2460 | */ |
| 2461 | mmc_bus_put(host); | 2461 | mmc_bus_put(host); |
| 2462 | 2462 | ||
| 2463 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) { | 2463 | if (!(host->caps & MMC_CAP_NONREMOVABLE) && host->ops->get_cd && |
| 2464 | host->ops->get_cd(host) == 0) { | ||
| 2464 | mmc_claim_host(host); | 2465 | mmc_claim_host(host); |
| 2465 | mmc_power_off(host); | 2466 | mmc_power_off(host); |
| 2466 | mmc_release_host(host); | 2467 | mmc_release_host(host); |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index f631f5a9bf79..98e9eb0f6643 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
| @@ -1119,14 +1119,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 1119 | */ | 1119 | */ |
| 1120 | if (mmc_card_highspeed(card)) { | 1120 | if (mmc_card_highspeed(card)) { |
| 1121 | if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) | 1121 | if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) |
| 1122 | && ((host->caps & (MMC_CAP_1_8V_DDR | | 1122 | && (host->caps & MMC_CAP_1_8V_DDR)) |
| 1123 | MMC_CAP_UHS_DDR50)) | ||
| 1124 | == (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50))) | ||
| 1125 | ddr = MMC_1_8V_DDR_MODE; | 1123 | ddr = MMC_1_8V_DDR_MODE; |
| 1126 | else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) | 1124 | else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) |
| 1127 | && ((host->caps & (MMC_CAP_1_2V_DDR | | 1125 | && (host->caps & MMC_CAP_1_2V_DDR)) |
| 1128 | MMC_CAP_UHS_DDR50)) | ||
| 1129 | == (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50))) | ||
| 1130 | ddr = MMC_1_2V_DDR_MODE; | 1126 | ddr = MMC_1_2V_DDR_MODE; |
| 1131 | } | 1127 | } |
| 1132 | 1128 | ||
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c index 06ee1aeaacec..6c36fccaa1ec 100644 --- a/drivers/mmc/core/quirks.c +++ b/drivers/mmc/core/quirks.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/export.h> | 14 | #include <linux/export.h> |
| 15 | #include <linux/mmc/card.h> | 15 | #include <linux/mmc/card.h> |
| 16 | #include <linux/mmc/sdio_ids.h> | ||
| 16 | 17 | ||
| 17 | #ifndef SDIO_VENDOR_ID_TI | 18 | #ifndef SDIO_VENDOR_ID_TI |
| 18 | #define SDIO_VENDOR_ID_TI 0x0097 | 19 | #define SDIO_VENDOR_ID_TI 0x0097 |
| @@ -30,6 +31,10 @@ | |||
| 30 | #define SDIO_DEVICE_ID_STE_CW1200 0x2280 | 31 | #define SDIO_DEVICE_ID_STE_CW1200 0x2280 |
| 31 | #endif | 32 | #endif |
| 32 | 33 | ||
| 34 | #ifndef SDIO_DEVICE_ID_MARVELL_8797_F0 | ||
| 35 | #define SDIO_DEVICE_ID_MARVELL_8797_F0 0x9128 | ||
| 36 | #endif | ||
| 37 | |||
| 33 | /* | 38 | /* |
| 34 | * This hook just adds a quirk for all sdio devices | 39 | * This hook just adds a quirk for all sdio devices |
| 35 | */ | 40 | */ |
| @@ -58,6 +63,9 @@ static const struct mmc_fixup mmc_fixup_methods[] = { | |||
| 58 | SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200, | 63 | SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200, |
| 59 | add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512), | 64 | add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512), |
| 60 | 65 | ||
| 66 | SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797_F0, | ||
| 67 | add_quirk, MMC_QUIRK_BROKEN_IRQ_POLLING), | ||
| 68 | |||
| 61 | END_FIXUP | 69 | END_FIXUP |
| 62 | }; | 70 | }; |
| 63 | 71 | ||
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 6f42050b7ccc..692fdb177294 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
| 14 | #include <linux/sizes.h> | ||
| 14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 15 | #include <linux/stat.h> | 16 | #include <linux/stat.h> |
| 16 | #include <linux/pm_runtime.h> | 17 | #include <linux/pm_runtime.h> |
| @@ -45,6 +46,13 @@ static const unsigned int tacc_mant[] = { | |||
| 45 | 35, 40, 45, 50, 55, 60, 70, 80, | 46 | 35, 40, 45, 50, 55, 60, 70, 80, |
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 49 | static const unsigned int sd_au_size[] = { | ||
| 50 | 0, SZ_16K / 512, SZ_32K / 512, SZ_64K / 512, | ||
| 51 | SZ_128K / 512, SZ_256K / 512, SZ_512K / 512, SZ_1M / 512, | ||
| 52 | SZ_2M / 512, SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512, | ||
| 53 | SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, SZ_64M / 512, | ||
| 54 | }; | ||
| 55 | |||
| 48 | #define UNSTUFF_BITS(resp,start,size) \ | 56 | #define UNSTUFF_BITS(resp,start,size) \ |
| 49 | ({ \ | 57 | ({ \ |
| 50 | const int __size = size; \ | 58 | const int __size = size; \ |
| @@ -216,7 +224,7 @@ static int mmc_decode_scr(struct mmc_card *card) | |||
| 216 | static int mmc_read_ssr(struct mmc_card *card) | 224 | static int mmc_read_ssr(struct mmc_card *card) |
| 217 | { | 225 | { |
| 218 | unsigned int au, es, et, eo; | 226 | unsigned int au, es, et, eo; |
| 219 | int err, i, max_au; | 227 | int err, i; |
| 220 | u32 *ssr; | 228 | u32 *ssr; |
| 221 | 229 | ||
| 222 | if (!(card->csd.cmdclass & CCC_APP_SPEC)) { | 230 | if (!(card->csd.cmdclass & CCC_APP_SPEC)) { |
| @@ -240,26 +248,25 @@ static int mmc_read_ssr(struct mmc_card *card) | |||
| 240 | for (i = 0; i < 16; i++) | 248 | for (i = 0; i < 16; i++) |
| 241 | ssr[i] = be32_to_cpu(ssr[i]); | 249 | ssr[i] = be32_to_cpu(ssr[i]); |
| 242 | 250 | ||
| 243 | /* SD3.0 increases max AU size to 64MB (0xF) from 4MB (0x9) */ | ||
| 244 | max_au = card->scr.sda_spec3 ? 0xF : 0x9; | ||
| 245 | |||
| 246 | /* | 251 | /* |
| 247 | * UNSTUFF_BITS only works with four u32s so we have to offset the | 252 | * UNSTUFF_BITS only works with four u32s so we have to offset the |
| 248 | * bitfield positions accordingly. | 253 | * bitfield positions accordingly. |
| 249 | */ | 254 | */ |
| 250 | au = UNSTUFF_BITS(ssr, 428 - 384, 4); | 255 | au = UNSTUFF_BITS(ssr, 428 - 384, 4); |
| 251 | if (au > 0 && au <= max_au) { | 256 | if (au) { |
| 252 | card->ssr.au = 1 << (au + 4); | 257 | if (au <= 9 || card->scr.sda_spec3) { |
| 253 | es = UNSTUFF_BITS(ssr, 408 - 384, 16); | 258 | card->ssr.au = sd_au_size[au]; |
| 254 | et = UNSTUFF_BITS(ssr, 402 - 384, 6); | 259 | es = UNSTUFF_BITS(ssr, 408 - 384, 16); |
| 255 | eo = UNSTUFF_BITS(ssr, 400 - 384, 2); | 260 | et = UNSTUFF_BITS(ssr, 402 - 384, 6); |
| 256 | if (es && et) { | 261 | if (es && et) { |
| 257 | card->ssr.erase_timeout = (et * 1000) / es; | 262 | eo = UNSTUFF_BITS(ssr, 400 - 384, 2); |
| 258 | card->ssr.erase_offset = eo * 1000; | 263 | card->ssr.erase_timeout = (et * 1000) / es; |
| 264 | card->ssr.erase_offset = eo * 1000; | ||
| 265 | } | ||
| 266 | } else { | ||
| 267 | pr_warning("%s: SD Status: Invalid Allocation Unit size.\n", | ||
| 268 | mmc_hostname(card->host)); | ||
| 259 | } | 269 | } |
| 260 | } else { | ||
| 261 | pr_warning("%s: SD Status: Invalid Allocation Unit " | ||
| 262 | "size.\n", mmc_hostname(card->host)); | ||
| 263 | } | 270 | } |
| 264 | out: | 271 | out: |
| 265 | kfree(ssr); | 272 | kfree(ssr); |
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 3d8ceb4084de..aaa90460ed23 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c | |||
| @@ -53,6 +53,17 @@ static int process_sdio_pending_irqs(struct mmc_host *host) | |||
| 53 | return ret; | 53 | return ret; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | if (pending && mmc_card_broken_irq_polling(card) && | ||
| 57 | !(host->caps & MMC_CAP_SDIO_IRQ)) { | ||
| 58 | unsigned char dummy; | ||
| 59 | |||
| 60 | /* A fake interrupt could be created when we poll SDIO_CCCR_INTx | ||
| 61 | * register with a Marvell SD8797 card. A dummy CMD52 read to | ||
| 62 | * function 0 register 0xff can avoid this. | ||
| 63 | */ | ||
| 64 | mmc_io_rw_direct(card, 0, 0, 0xff, 0, &dummy); | ||
| 65 | } | ||
| 66 | |||
| 56 | count = 0; | 67 | count = 0; |
| 57 | for (i = 1; i <= 7; i++) { | 68 | for (i = 1; i <= 7; i++) { |
| 58 | if (pending & (1 << i)) { | 69 | if (pending & (1 << i)) { |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 4e8ca9d5570f..1384f67abe21 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -104,6 +104,18 @@ config MMC_SDHCI_PLTFM | |||
| 104 | 104 | ||
| 105 | If unsure, say N. | 105 | If unsure, say N. |
| 106 | 106 | ||
| 107 | config MMC_SDHCI_OF_ARASAN | ||
| 108 | tristate "SDHCI OF support for the Arasan SDHCI controllers" | ||
| 109 | depends on MMC_SDHCI_PLTFM | ||
| 110 | depends on OF | ||
| 111 | help | ||
| 112 | This selects the Arasan Secure Digital Host Controller Interface | ||
| 113 | (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC. | ||
| 114 | |||
| 115 | If you have a controller with this interface, say Y or M here. | ||
| 116 | |||
| 117 | If unsure, say N. | ||
| 118 | |||
| 107 | config MMC_SDHCI_OF_ESDHC | 119 | config MMC_SDHCI_OF_ESDHC |
| 108 | tristate "SDHCI OF support for the Freescale eSDHC controller" | 120 | tristate "SDHCI OF support for the Freescale eSDHC controller" |
| 109 | depends on MMC_SDHCI_PLTFM | 121 | depends on MMC_SDHCI_PLTFM |
| @@ -479,7 +491,8 @@ config MMC_TMIO | |||
| 479 | 491 | ||
| 480 | config MMC_SDHI | 492 | config MMC_SDHI |
| 481 | tristate "SH-Mobile SDHI SD/SDIO controller support" | 493 | tristate "SH-Mobile SDHI SD/SDIO controller support" |
| 482 | depends on SUPERH || ARCH_SHMOBILE | 494 | depends on SUPERH || ARM |
| 495 | depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST | ||
| 483 | select MMC_TMIO_CORE | 496 | select MMC_TMIO_CORE |
| 484 | help | 497 | help |
| 485 | This provides support for the SDHI SD/SDIO controller found in | 498 | This provides support for the SDHI SD/SDIO controller found in |
| @@ -575,6 +588,16 @@ config MMC_DW_SOCFPGA | |||
| 575 | This selects support for Altera SoCFPGA specific extensions to the | 588 | This selects support for Altera SoCFPGA specific extensions to the |
| 576 | Synopsys DesignWare Memory Card Interface driver. | 589 | Synopsys DesignWare Memory Card Interface driver. |
| 577 | 590 | ||
| 591 | config MMC_DW_K3 | ||
| 592 | tristate "K3 specific extensions for Synopsys DW Memory Card Interface" | ||
| 593 | depends on MMC_DW | ||
| 594 | select MMC_DW_PLTFM | ||
| 595 | select MMC_DW_IDMAC | ||
| 596 | help | ||
| 597 | This selects support for Hisilicon K3 SoC specific extensions to the | ||
| 598 | Synopsys DesignWare Memory Card Interface driver. Select this option | ||
| 599 | for platforms based on Hisilicon K3 SoC's. | ||
| 600 | |||
| 578 | config MMC_DW_PCI | 601 | config MMC_DW_PCI |
| 579 | tristate "Synopsys Designware MCI support on PCI bus" | 602 | tristate "Synopsys Designware MCI support on PCI bus" |
| 580 | depends on MMC_DW && PCI | 603 | depends on MMC_DW && PCI |
| @@ -588,7 +611,8 @@ config MMC_DW_PCI | |||
| 588 | 611 | ||
| 589 | config MMC_SH_MMCIF | 612 | config MMC_SH_MMCIF |
| 590 | tristate "SuperH Internal MMCIF support" | 613 | tristate "SuperH Internal MMCIF support" |
| 591 | depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE) | 614 | depends on MMC_BLOCK |
| 615 | depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST | ||
| 592 | help | 616 | help |
| 593 | This selects the MMC Host Interface controller (MMCIF). | 617 | This selects the MMC Host Interface controller (MMCIF). |
| 594 | 618 | ||
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index c41d0c364509..3483b6b6b880 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
| @@ -9,6 +9,7 @@ obj-$(CONFIG_MMC_MXS) += mxs-mmc.o | |||
| 9 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o | 9 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o |
| 10 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o | 10 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o |
| 11 | obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o | 11 | obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o |
| 12 | obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-o2micro.o | ||
| 12 | obj-$(CONFIG_MMC_SDHCI_ACPI) += sdhci-acpi.o | 13 | obj-$(CONFIG_MMC_SDHCI_ACPI) += sdhci-acpi.o |
| 13 | obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o | 14 | obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o |
| 14 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o | 15 | obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o |
| @@ -43,6 +44,7 @@ obj-$(CONFIG_MMC_DW) += dw_mmc.o | |||
| 43 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o | 44 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o |
| 44 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o | 45 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o |
| 45 | obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o | 46 | obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o |
| 47 | obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o | ||
| 46 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o | 48 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o |
| 47 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o | 49 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o |
| 48 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o | 50 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o |
| @@ -57,6 +59,7 @@ obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o | |||
| 57 | obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o | 59 | obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o |
| 58 | obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o | 60 | obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o |
| 59 | obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o | 61 | obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o |
| 62 | obj-$(CONFIG_MMC_SDHCI_OF_ARASAN) += sdhci-of-arasan.o | ||
| 60 | obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o | 63 | obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o |
| 61 | obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o | 64 | obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o |
| 62 | obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o | 65 | obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 2cbb4516d353..42706ea0ba85 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
| @@ -1192,11 +1192,22 @@ static void atmci_start_request(struct atmel_mci *host, | |||
| 1192 | iflags |= ATMCI_CMDRDY; | 1192 | iflags |= ATMCI_CMDRDY; |
| 1193 | cmd = mrq->cmd; | 1193 | cmd = mrq->cmd; |
| 1194 | cmdflags = atmci_prepare_command(slot->mmc, cmd); | 1194 | cmdflags = atmci_prepare_command(slot->mmc, cmd); |
| 1195 | atmci_send_command(host, cmd, cmdflags); | 1195 | |
| 1196 | /* | ||
| 1197 | * DMA transfer should be started before sending the command to avoid | ||
| 1198 | * unexpected errors especially for read operations in SDIO mode. | ||
| 1199 | * Unfortunately, in PDC mode, command has to be sent before starting | ||
| 1200 | * the transfer. | ||
| 1201 | */ | ||
| 1202 | if (host->submit_data != &atmci_submit_data_dma) | ||
| 1203 | atmci_send_command(host, cmd, cmdflags); | ||
| 1196 | 1204 | ||
| 1197 | if (data) | 1205 | if (data) |
| 1198 | host->submit_data(host, data); | 1206 | host->submit_data(host, data); |
| 1199 | 1207 | ||
| 1208 | if (host->submit_data == &atmci_submit_data_dma) | ||
| 1209 | atmci_send_command(host, cmd, cmdflags); | ||
| 1210 | |||
| 1200 | if (mrq->stop) { | 1211 | if (mrq->stop) { |
| 1201 | host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); | 1212 | host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); |
| 1202 | host->stop_cmdr |= ATMCI_CMDR_STOP_XFER; | 1213 | host->stop_cmdr |= ATMCI_CMDR_STOP_XFER; |
| @@ -1391,8 +1402,14 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 1391 | clk_unprepare(host->mck); | 1402 | clk_unprepare(host->mck); |
| 1392 | 1403 | ||
| 1393 | switch (ios->power_mode) { | 1404 | switch (ios->power_mode) { |
| 1405 | case MMC_POWER_OFF: | ||
| 1406 | if (!IS_ERR(mmc->supply.vmmc)) | ||
| 1407 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); | ||
| 1408 | break; | ||
| 1394 | case MMC_POWER_UP: | 1409 | case MMC_POWER_UP: |
| 1395 | set_bit(ATMCI_CARD_NEED_INIT, &slot->flags); | 1410 | set_bit(ATMCI_CARD_NEED_INIT, &slot->flags); |
| 1411 | if (!IS_ERR(mmc->supply.vmmc)) | ||
| 1412 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); | ||
| 1396 | break; | 1413 | break; |
| 1397 | default: | 1414 | default: |
| 1398 | /* | 1415 | /* |
| @@ -2204,6 +2221,7 @@ static int __init atmci_init_slot(struct atmel_mci *host, | |||
| 2204 | } | 2221 | } |
| 2205 | 2222 | ||
| 2206 | host->slot[id] = slot; | 2223 | host->slot[id] = slot; |
| 2224 | mmc_regulator_get_supply(mmc); | ||
| 2207 | mmc_add_host(mmc); | 2225 | mmc_add_host(mmc); |
| 2208 | 2226 | ||
| 2209 | if (gpio_is_valid(slot->detect_pin)) { | 2227 | if (gpio_is_valid(slot->detect_pin)) { |
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c new file mode 100644 index 000000000000..f567c219cff4 --- /dev/null +++ b/drivers/mmc/host/dw_mmc-k3.c | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 Linaro Ltd. | ||
| 3 | * Copyright (c) 2013 Hisilicon Limited. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/clk.h> | ||
| 14 | #include <linux/mmc/host.h> | ||
| 15 | #include <linux/mmc/dw_mmc.h> | ||
| 16 | #include <linux/of_address.h> | ||
| 17 | |||
| 18 | #include "dw_mmc.h" | ||
| 19 | #include "dw_mmc-pltfm.h" | ||
| 20 | |||
| 21 | static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios) | ||
| 22 | { | ||
| 23 | int ret; | ||
| 24 | |||
| 25 | ret = clk_set_rate(host->ciu_clk, ios->clock); | ||
| 26 | if (ret) | ||
| 27 | dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock); | ||
| 28 | |||
| 29 | host->bus_hz = clk_get_rate(host->ciu_clk); | ||
| 30 | } | ||
| 31 | |||
| 32 | static const struct dw_mci_drv_data k3_drv_data = { | ||
| 33 | .set_ios = dw_mci_k3_set_ios, | ||
| 34 | }; | ||
| 35 | |||
| 36 | static const struct of_device_id dw_mci_k3_match[] = { | ||
| 37 | { .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, }, | ||
| 38 | {}, | ||
| 39 | }; | ||
| 40 | MODULE_DEVICE_TABLE(of, dw_mci_k3_match); | ||
| 41 | |||
| 42 | static int dw_mci_k3_probe(struct platform_device *pdev) | ||
| 43 | { | ||
| 44 | const struct dw_mci_drv_data *drv_data; | ||
| 45 | const struct of_device_id *match; | ||
| 46 | |||
| 47 | match = of_match_node(dw_mci_k3_match, pdev->dev.of_node); | ||
| 48 | drv_data = match->data; | ||
| 49 | |||
| 50 | return dw_mci_pltfm_register(pdev, drv_data); | ||
| 51 | } | ||
| 52 | |||
| 53 | static int dw_mci_k3_suspend(struct device *dev) | ||
| 54 | { | ||
| 55 | struct dw_mci *host = dev_get_drvdata(dev); | ||
| 56 | int ret; | ||
| 57 | |||
| 58 | ret = dw_mci_suspend(host); | ||
| 59 | if (!ret) | ||
| 60 | clk_disable_unprepare(host->ciu_clk); | ||
| 61 | |||
| 62 | return ret; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int dw_mci_k3_resume(struct device *dev) | ||
| 66 | { | ||
| 67 | struct dw_mci *host = dev_get_drvdata(dev); | ||
| 68 | int ret; | ||
| 69 | |||
| 70 | ret = clk_prepare_enable(host->ciu_clk); | ||
| 71 | if (ret) { | ||
| 72 | dev_err(host->dev, "failed to enable ciu clock\n"); | ||
| 73 | return ret; | ||
| 74 | } | ||
| 75 | |||
| 76 | return dw_mci_resume(host); | ||
| 77 | } | ||
| 78 | |||
| 79 | static SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume); | ||
| 80 | |||
| 81 | static struct platform_driver dw_mci_k3_pltfm_driver = { | ||
| 82 | .probe = dw_mci_k3_probe, | ||
| 83 | .remove = dw_mci_pltfm_remove, | ||
| 84 | .driver = { | ||
| 85 | .name = "dwmmc_k3", | ||
| 86 | .of_match_table = dw_mci_k3_match, | ||
| 87 | .pm = &dw_mci_k3_pmops, | ||
| 88 | }, | ||
| 89 | }; | ||
| 90 | |||
| 91 | module_platform_driver(dw_mci_k3_pltfm_driver); | ||
| 92 | |||
| 93 | MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension"); | ||
| 94 | MODULE_LICENSE("GPL v2"); | ||
| 95 | MODULE_ALIAS("platform:dwmmc-k3"); | ||
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 4bce0deec362..55cd110a49c4 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
| 37 | #include <linux/of.h> | 37 | #include <linux/of.h> |
| 38 | #include <linux/of_gpio.h> | 38 | #include <linux/of_gpio.h> |
| 39 | #include <linux/mmc/slot-gpio.h> | ||
| 39 | 40 | ||
| 40 | #include "dw_mmc.h" | 41 | #include "dw_mmc.h" |
| 41 | 42 | ||
| @@ -1032,20 +1033,29 @@ static int dw_mci_get_cd(struct mmc_host *mmc) | |||
| 1032 | int present; | 1033 | int present; |
| 1033 | struct dw_mci_slot *slot = mmc_priv(mmc); | 1034 | struct dw_mci_slot *slot = mmc_priv(mmc); |
| 1034 | struct dw_mci_board *brd = slot->host->pdata; | 1035 | struct dw_mci_board *brd = slot->host->pdata; |
| 1036 | struct dw_mci *host = slot->host; | ||
| 1037 | int gpio_cd = mmc_gpio_get_cd(mmc); | ||
| 1035 | 1038 | ||
| 1036 | /* Use platform get_cd function, else try onboard card detect */ | 1039 | /* Use platform get_cd function, else try onboard card detect */ |
| 1037 | if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) | 1040 | if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) |
| 1038 | present = 1; | 1041 | present = 1; |
| 1039 | else if (brd->get_cd) | 1042 | else if (brd->get_cd) |
| 1040 | present = !brd->get_cd(slot->id); | 1043 | present = !brd->get_cd(slot->id); |
| 1044 | else if (!IS_ERR_VALUE(gpio_cd)) | ||
| 1045 | present = gpio_cd; | ||
| 1041 | else | 1046 | else |
| 1042 | present = (mci_readl(slot->host, CDETECT) & (1 << slot->id)) | 1047 | present = (mci_readl(slot->host, CDETECT) & (1 << slot->id)) |
| 1043 | == 0 ? 1 : 0; | 1048 | == 0 ? 1 : 0; |
| 1044 | 1049 | ||
| 1045 | if (present) | 1050 | spin_lock_bh(&host->lock); |
| 1051 | if (present) { | ||
| 1052 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
| 1046 | dev_dbg(&mmc->class_dev, "card is present\n"); | 1053 | dev_dbg(&mmc->class_dev, "card is present\n"); |
| 1047 | else | 1054 | } else { |
| 1055 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
| 1048 | dev_dbg(&mmc->class_dev, "card is not present\n"); | 1056 | dev_dbg(&mmc->class_dev, "card is not present\n"); |
| 1057 | } | ||
| 1058 | spin_unlock_bh(&host->lock); | ||
| 1049 | 1059 | ||
| 1050 | return present; | 1060 | return present; |
| 1051 | } | 1061 | } |
| @@ -1926,10 +1936,6 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
| 1926 | /* Card change detected */ | 1936 | /* Card change detected */ |
| 1927 | slot->last_detect_state = present; | 1937 | slot->last_detect_state = present; |
| 1928 | 1938 | ||
| 1929 | /* Mark card as present if applicable */ | ||
| 1930 | if (present != 0) | ||
| 1931 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
| 1932 | |||
| 1933 | /* Clean up queue if present */ | 1939 | /* Clean up queue if present */ |
| 1934 | mrq = slot->mrq; | 1940 | mrq = slot->mrq; |
| 1935 | if (mrq) { | 1941 | if (mrq) { |
| @@ -1977,8 +1983,6 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
| 1977 | 1983 | ||
| 1978 | /* Power down slot */ | 1984 | /* Power down slot */ |
| 1979 | if (present == 0) { | 1985 | if (present == 0) { |
| 1980 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
| 1981 | |||
| 1982 | /* Clear down the FIFO */ | 1986 | /* Clear down the FIFO */ |
| 1983 | dw_mci_fifo_reset(host); | 1987 | dw_mci_fifo_reset(host); |
| 1984 | #ifdef CONFIG_MMC_DW_IDMAC | 1988 | #ifdef CONFIG_MMC_DW_IDMAC |
| @@ -2079,6 +2083,26 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot) | |||
| 2079 | 2083 | ||
| 2080 | return gpio; | 2084 | return gpio; |
| 2081 | } | 2085 | } |
| 2086 | |||
| 2087 | /* find the cd gpio for a given slot */ | ||
| 2088 | static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot, | ||
| 2089 | struct mmc_host *mmc) | ||
| 2090 | { | ||
| 2091 | struct device_node *np = dw_mci_of_find_slot_node(dev, slot); | ||
| 2092 | int gpio; | ||
| 2093 | |||
| 2094 | if (!np) | ||
| 2095 | return; | ||
| 2096 | |||
| 2097 | gpio = of_get_named_gpio(np, "cd-gpios", 0); | ||
| 2098 | |||
| 2099 | /* Having a missing entry is valid; return silently */ | ||
| 2100 | if (!gpio_is_valid(gpio)) | ||
| 2101 | return; | ||
| 2102 | |||
| 2103 | if (mmc_gpio_request_cd(mmc, gpio, 0)) | ||
| 2104 | dev_warn(dev, "gpio [%d] request failed\n", gpio); | ||
| 2105 | } | ||
| 2082 | #else /* CONFIG_OF */ | 2106 | #else /* CONFIG_OF */ |
| 2083 | static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) | 2107 | static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) |
| 2084 | { | 2108 | { |
| @@ -2096,6 +2120,11 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot) | |||
| 2096 | { | 2120 | { |
| 2097 | return -EINVAL; | 2121 | return -EINVAL; |
| 2098 | } | 2122 | } |
| 2123 | static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot, | ||
| 2124 | struct mmc_host *mmc) | ||
| 2125 | { | ||
| 2126 | return; | ||
| 2127 | } | ||
| 2099 | #endif /* CONFIG_OF */ | 2128 | #endif /* CONFIG_OF */ |
| 2100 | 2129 | ||
| 2101 | static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | 2130 | static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) |
| @@ -2197,12 +2226,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
| 2197 | #endif /* CONFIG_MMC_DW_IDMAC */ | 2226 | #endif /* CONFIG_MMC_DW_IDMAC */ |
| 2198 | } | 2227 | } |
| 2199 | 2228 | ||
| 2200 | if (dw_mci_get_cd(mmc)) | ||
| 2201 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
| 2202 | else | ||
| 2203 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
| 2204 | |||
| 2205 | slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id); | 2229 | slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id); |
| 2230 | dw_mci_of_get_cd_gpio(host->dev, slot->id, mmc); | ||
| 2206 | 2231 | ||
| 2207 | ret = mmc_add_host(mmc); | 2232 | ret = mmc_add_host(mmc); |
| 2208 | if (ret) | 2233 | if (ret) |
| @@ -2389,6 +2414,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | |||
| 2389 | if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL)) | 2414 | if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL)) |
| 2390 | pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR; | 2415 | pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR; |
| 2391 | 2416 | ||
| 2417 | if (of_get_property(np, "cd-inverted", NULL)) | ||
| 2418 | pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; | ||
| 2419 | |||
| 2392 | return pdata; | 2420 | return pdata; |
| 2393 | } | 2421 | } |
| 2394 | 2422 | ||
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 50fc9df791b2..073e871a0fc8 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/mmc/host.h> | 38 | #include <linux/mmc/host.h> |
| 39 | #include <linux/mmc/mmc.h> | 39 | #include <linux/mmc/mmc.h> |
| 40 | #include <linux/mmc/sdio.h> | 40 | #include <linux/mmc/sdio.h> |
| 41 | #include <linux/mmc/slot-gpio.h> | ||
| 41 | #include <linux/gpio.h> | 42 | #include <linux/gpio.h> |
| 42 | #include <linux/regulator/consumer.h> | 43 | #include <linux/regulator/consumer.h> |
| 43 | #include <linux/module.h> | 44 | #include <linux/module.h> |
| @@ -69,37 +70,25 @@ struct mxs_mmc_host { | |||
| 69 | unsigned char bus_width; | 70 | unsigned char bus_width; |
| 70 | spinlock_t lock; | 71 | spinlock_t lock; |
| 71 | int sdio_irq_en; | 72 | int sdio_irq_en; |
| 72 | int wp_gpio; | ||
| 73 | bool wp_inverted; | ||
| 74 | bool cd_inverted; | ||
| 75 | bool broken_cd; | ||
| 76 | bool non_removable; | ||
| 77 | }; | 73 | }; |
| 78 | 74 | ||
| 79 | static int mxs_mmc_get_ro(struct mmc_host *mmc) | 75 | static int mxs_mmc_get_cd(struct mmc_host *mmc) |
| 80 | { | 76 | { |
| 81 | struct mxs_mmc_host *host = mmc_priv(mmc); | 77 | struct mxs_mmc_host *host = mmc_priv(mmc); |
| 82 | int ret; | 78 | struct mxs_ssp *ssp = &host->ssp; |
| 83 | 79 | int present, ret; | |
| 84 | if (!gpio_is_valid(host->wp_gpio)) | ||
| 85 | return -EINVAL; | ||
| 86 | |||
| 87 | ret = gpio_get_value(host->wp_gpio); | ||
| 88 | 80 | ||
| 89 | if (host->wp_inverted) | 81 | ret = mmc_gpio_get_cd(mmc); |
| 90 | ret = !ret; | 82 | if (ret >= 0) |
| 83 | return ret; | ||
| 91 | 84 | ||
| 92 | return ret; | 85 | present = !(readl(ssp->base + HW_SSP_STATUS(ssp)) & |
| 93 | } | 86 | BM_SSP_STATUS_CARD_DETECT); |
| 94 | 87 | ||
| 95 | static int mxs_mmc_get_cd(struct mmc_host *mmc) | 88 | if (mmc->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) |
| 96 | { | 89 | present = !present; |
| 97 | struct mxs_mmc_host *host = mmc_priv(mmc); | ||
| 98 | struct mxs_ssp *ssp = &host->ssp; | ||
| 99 | 90 | ||
| 100 | return host->non_removable || host->broken_cd || | 91 | return present; |
| 101 | !(readl(ssp->base + HW_SSP_STATUS(ssp)) & | ||
| 102 | BM_SSP_STATUS_CARD_DETECT) ^ host->cd_inverted; | ||
| 103 | } | 92 | } |
| 104 | 93 | ||
| 105 | static int mxs_mmc_reset(struct mxs_mmc_host *host) | 94 | static int mxs_mmc_reset(struct mxs_mmc_host *host) |
| @@ -549,7 +538,7 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
| 549 | 538 | ||
| 550 | static const struct mmc_host_ops mxs_mmc_ops = { | 539 | static const struct mmc_host_ops mxs_mmc_ops = { |
| 551 | .request = mxs_mmc_request, | 540 | .request = mxs_mmc_request, |
| 552 | .get_ro = mxs_mmc_get_ro, | 541 | .get_ro = mmc_gpio_get_ro, |
| 553 | .get_cd = mxs_mmc_get_cd, | 542 | .get_cd = mxs_mmc_get_cd, |
| 554 | .set_ios = mxs_mmc_set_ios, | 543 | .set_ios = mxs_mmc_set_ios, |
| 555 | .enable_sdio_irq = mxs_mmc_enable_sdio_irq, | 544 | .enable_sdio_irq = mxs_mmc_enable_sdio_irq, |
| @@ -579,15 +568,12 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
| 579 | { | 568 | { |
| 580 | const struct of_device_id *of_id = | 569 | const struct of_device_id *of_id = |
| 581 | of_match_device(mxs_mmc_dt_ids, &pdev->dev); | 570 | of_match_device(mxs_mmc_dt_ids, &pdev->dev); |
| 582 | struct device_node *np = pdev->dev.of_node; | ||
| 583 | struct mxs_mmc_host *host; | 571 | struct mxs_mmc_host *host; |
| 584 | struct mmc_host *mmc; | 572 | struct mmc_host *mmc; |
| 585 | struct resource *iores; | 573 | struct resource *iores; |
| 586 | int ret = 0, irq_err; | 574 | int ret = 0, irq_err; |
| 587 | struct regulator *reg_vmmc; | 575 | struct regulator *reg_vmmc; |
| 588 | enum of_gpio_flags flags; | ||
| 589 | struct mxs_ssp *ssp; | 576 | struct mxs_ssp *ssp; |
| 590 | u32 bus_width = 0; | ||
| 591 | 577 | ||
| 592 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 578 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 593 | irq_err = platform_get_irq(pdev, 0); | 579 | irq_err = platform_get_irq(pdev, 0); |
| @@ -648,23 +634,13 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
| 648 | mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | | 634 | mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | |
| 649 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL; | 635 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL; |
| 650 | 636 | ||
| 651 | of_property_read_u32(np, "bus-width", &bus_width); | ||
| 652 | if (bus_width == 4) | ||
| 653 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
| 654 | else if (bus_width == 8) | ||
| 655 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; | ||
| 656 | host->broken_cd = of_property_read_bool(np, "broken-cd"); | ||
| 657 | host->non_removable = of_property_read_bool(np, "non-removable"); | ||
| 658 | if (host->non_removable) | ||
| 659 | mmc->caps |= MMC_CAP_NONREMOVABLE; | ||
| 660 | host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags); | ||
| 661 | if (flags & OF_GPIO_ACTIVE_LOW) | ||
| 662 | host->wp_inverted = 1; | ||
| 663 | |||
| 664 | host->cd_inverted = of_property_read_bool(np, "cd-inverted"); | ||
| 665 | |||
| 666 | mmc->f_min = 400000; | 637 | mmc->f_min = 400000; |
| 667 | mmc->f_max = 288000000; | 638 | mmc->f_max = 288000000; |
| 639 | |||
| 640 | ret = mmc_of_parse(mmc); | ||
| 641 | if (ret) | ||
| 642 | goto out_clk_disable; | ||
| 643 | |||
| 668 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 644 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
| 669 | 645 | ||
| 670 | mmc->max_segs = 52; | 646 | mmc->max_segs = 52; |
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 4ede2307b293..9ce17f6e4014 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c | |||
| @@ -143,6 +143,7 @@ static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = { | |||
| 143 | { "80860F14" , "3" , &sdhci_acpi_slot_int_sd }, | 143 | { "80860F14" , "3" , &sdhci_acpi_slot_int_sd }, |
| 144 | { "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio }, | 144 | { "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio }, |
| 145 | { "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio }, | 145 | { "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio }, |
| 146 | { "INT3436" , NULL, &sdhci_acpi_slot_int_sdio }, | ||
| 146 | { "PNP0D40" }, | 147 | { "PNP0D40" }, |
| 147 | { }, | 148 | { }, |
| 148 | }; | 149 | }; |
| @@ -151,6 +152,7 @@ static const struct acpi_device_id sdhci_acpi_ids[] = { | |||
| 151 | { "80860F14" }, | 152 | { "80860F14" }, |
| 152 | { "INT33BB" }, | 153 | { "INT33BB" }, |
| 153 | { "INT33C6" }, | 154 | { "INT33C6" }, |
| 155 | { "INT3436" }, | ||
| 154 | { "PNP0D40" }, | 156 | { "PNP0D40" }, |
| 155 | { }, | 157 | { }, |
| 156 | }; | 158 | }; |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 461a4c3f4ef7..b841bb7cd371 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/of_gpio.h> | 27 | #include <linux/of_gpio.h> |
| 28 | #include <linux/pinctrl/consumer.h> | 28 | #include <linux/pinctrl/consumer.h> |
| 29 | #include <linux/platform_data/mmc-esdhc-imx.h> | 29 | #include <linux/platform_data/mmc-esdhc-imx.h> |
| 30 | #include <linux/pm_runtime.h> | ||
| 30 | #include "sdhci-pltfm.h" | 31 | #include "sdhci-pltfm.h" |
| 31 | #include "sdhci-esdhc.h" | 32 | #include "sdhci-esdhc.h" |
| 32 | 33 | ||
| @@ -45,6 +46,8 @@ | |||
| 45 | #define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25) | 46 | #define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25) |
| 46 | /* Bits 3 and 6 are not SDHCI standard definitions */ | 47 | /* Bits 3 and 6 are not SDHCI standard definitions */ |
| 47 | #define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7 | 48 | #define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7 |
| 49 | /* Tuning bits */ | ||
| 50 | #define ESDHC_MIX_CTRL_TUNING_MASK 0x03c00000 | ||
| 48 | 51 | ||
| 49 | /* dll control register */ | 52 | /* dll control register */ |
| 50 | #define ESDHC_DLL_CTRL 0x60 | 53 | #define ESDHC_DLL_CTRL 0x60 |
| @@ -385,6 +388,22 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) | |||
| 385 | return ret; | 388 | return ret; |
| 386 | } | 389 | } |
| 387 | 390 | ||
| 391 | if (unlikely(reg == SDHCI_TRANSFER_MODE)) { | ||
| 392 | if (esdhc_is_usdhc(imx_data)) { | ||
| 393 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); | ||
| 394 | ret = m & ESDHC_MIX_CTRL_SDHCI_MASK; | ||
| 395 | /* Swap AC23 bit */ | ||
| 396 | if (m & ESDHC_MIX_CTRL_AC23EN) { | ||
| 397 | ret &= ~ESDHC_MIX_CTRL_AC23EN; | ||
| 398 | ret |= SDHCI_TRNS_AUTO_CMD23; | ||
| 399 | } | ||
| 400 | } else { | ||
| 401 | ret = readw(host->ioaddr + SDHCI_TRANSFER_MODE); | ||
| 402 | } | ||
| 403 | |||
| 404 | return ret; | ||
| 405 | } | ||
| 406 | |||
| 388 | return readw(host->ioaddr + reg); | 407 | return readw(host->ioaddr + reg); |
| 389 | } | 408 | } |
| 390 | 409 | ||
| @@ -421,24 +440,20 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |||
| 421 | } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { | 440 | } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { |
| 422 | u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR); | 441 | u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR); |
| 423 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); | 442 | u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); |
| 424 | new_val = readl(host->ioaddr + ESDHC_TUNING_CTRL); | 443 | if (val & SDHCI_CTRL_TUNED_CLK) { |
| 444 | v |= ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
| 445 | } else { | ||
| 446 | v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
| 447 | m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; | ||
| 448 | } | ||
| 449 | |||
| 425 | if (val & SDHCI_CTRL_EXEC_TUNING) { | 450 | if (val & SDHCI_CTRL_EXEC_TUNING) { |
| 426 | new_val |= ESDHC_STD_TUNING_EN | | ||
| 427 | ESDHC_TUNING_START_TAP; | ||
| 428 | v |= ESDHC_MIX_CTRL_EXE_TUNE; | 451 | v |= ESDHC_MIX_CTRL_EXE_TUNE; |
| 429 | m |= ESDHC_MIX_CTRL_FBCLK_SEL; | 452 | m |= ESDHC_MIX_CTRL_FBCLK_SEL; |
| 430 | } else { | 453 | } else { |
| 431 | new_val &= ~ESDHC_STD_TUNING_EN; | ||
| 432 | v &= ~ESDHC_MIX_CTRL_EXE_TUNE; | 454 | v &= ~ESDHC_MIX_CTRL_EXE_TUNE; |
| 433 | m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; | ||
| 434 | } | 455 | } |
| 435 | 456 | ||
| 436 | if (val & SDHCI_CTRL_TUNED_CLK) | ||
| 437 | v |= ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
| 438 | else | ||
| 439 | v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; | ||
| 440 | |||
| 441 | writel(new_val, host->ioaddr + ESDHC_TUNING_CTRL); | ||
| 442 | writel(v, host->ioaddr + SDHCI_ACMD12_ERR); | 457 | writel(v, host->ioaddr + SDHCI_ACMD12_ERR); |
| 443 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); | 458 | writel(m, host->ioaddr + ESDHC_MIX_CTRL); |
| 444 | } | 459 | } |
| @@ -546,7 +561,10 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) | |||
| 546 | * Do it manually here. | 561 | * Do it manually here. |
| 547 | */ | 562 | */ |
| 548 | if (esdhc_is_usdhc(imx_data)) { | 563 | if (esdhc_is_usdhc(imx_data)) { |
| 549 | writel(0, host->ioaddr + ESDHC_MIX_CTRL); | 564 | /* the tuning bits should be kept during reset */ |
| 565 | new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); | ||
| 566 | writel(new_val & ESDHC_MIX_CTRL_TUNING_MASK, | ||
| 567 | host->ioaddr + ESDHC_MIX_CTRL); | ||
| 550 | imx_data->is_ddr = 0; | 568 | imx_data->is_ddr = 0; |
| 551 | } | 569 | } |
| 552 | } | 570 | } |
| @@ -558,19 +576,17 @@ static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) | |||
| 558 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | 576 | struct pltfm_imx_data *imx_data = pltfm_host->priv; |
| 559 | struct esdhc_platform_data *boarddata = &imx_data->boarddata; | 577 | struct esdhc_platform_data *boarddata = &imx_data->boarddata; |
| 560 | 578 | ||
| 561 | u32 f_host = clk_get_rate(pltfm_host->clk); | 579 | if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock)) |
| 562 | |||
| 563 | if (boarddata->f_max && (boarddata->f_max < f_host)) | ||
| 564 | return boarddata->f_max; | 580 | return boarddata->f_max; |
| 565 | else | 581 | else |
| 566 | return f_host; | 582 | return pltfm_host->clock; |
| 567 | } | 583 | } |
| 568 | 584 | ||
| 569 | static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) | 585 | static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) |
| 570 | { | 586 | { |
| 571 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 587 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 572 | 588 | ||
| 573 | return clk_get_rate(pltfm_host->clk) / 256 / 16; | 589 | return pltfm_host->clock / 256 / 16; |
| 574 | } | 590 | } |
| 575 | 591 | ||
| 576 | static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, | 592 | static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, |
| @@ -578,7 +594,7 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, | |||
| 578 | { | 594 | { |
| 579 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 595 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 580 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | 596 | struct pltfm_imx_data *imx_data = pltfm_host->priv; |
| 581 | unsigned int host_clock = clk_get_rate(pltfm_host->clk); | 597 | unsigned int host_clock = pltfm_host->clock; |
| 582 | int pre_div = 2; | 598 | int pre_div = 2; |
| 583 | int div = 1; | 599 | int div = 1; |
| 584 | u32 temp, val; | 600 | u32 temp, val; |
| @@ -681,6 +697,7 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) | |||
| 681 | /* FIXME: delay a bit for card to be ready for next tuning due to errors */ | 697 | /* FIXME: delay a bit for card to be ready for next tuning due to errors */ |
| 682 | mdelay(1); | 698 | mdelay(1); |
| 683 | 699 | ||
| 700 | pm_runtime_get_sync(host->mmc->parent); | ||
| 684 | reg = readl(host->ioaddr + ESDHC_MIX_CTRL); | 701 | reg = readl(host->ioaddr + ESDHC_MIX_CTRL); |
| 685 | reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | | 702 | reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | |
| 686 | ESDHC_MIX_CTRL_FBCLK_SEL; | 703 | ESDHC_MIX_CTRL_FBCLK_SEL; |
| @@ -699,7 +716,7 @@ static void esdhc_request_done(struct mmc_request *mrq) | |||
| 699 | static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode) | 716 | static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode) |
| 700 | { | 717 | { |
| 701 | struct mmc_command cmd = {0}; | 718 | struct mmc_command cmd = {0}; |
| 702 | struct mmc_request mrq = {0}; | 719 | struct mmc_request mrq = {NULL}; |
| 703 | struct mmc_data data = {0}; | 720 | struct mmc_data data = {0}; |
| 704 | struct scatterlist sg; | 721 | struct scatterlist sg; |
| 705 | char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN]; | 722 | char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN]; |
| @@ -809,6 +826,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host, | |||
| 809 | pinctrl = imx_data->pins_100mhz; | 826 | pinctrl = imx_data->pins_100mhz; |
| 810 | break; | 827 | break; |
| 811 | case MMC_TIMING_UHS_SDR104: | 828 | case MMC_TIMING_UHS_SDR104: |
| 829 | case MMC_TIMING_MMC_HS200: | ||
| 812 | pinctrl = imx_data->pins_200mhz; | 830 | pinctrl = imx_data->pins_200mhz; |
| 813 | break; | 831 | break; |
| 814 | default: | 832 | default: |
| @@ -836,6 +854,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) | |||
| 836 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50; | 854 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50; |
| 837 | break; | 855 | break; |
| 838 | case MMC_TIMING_UHS_SDR104: | 856 | case MMC_TIMING_UHS_SDR104: |
| 857 | case MMC_TIMING_MMC_HS200: | ||
| 839 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104; | 858 | imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104; |
| 840 | break; | 859 | break; |
| 841 | case MMC_TIMING_UHS_DDR50: | 860 | case MMC_TIMING_UHS_DDR50: |
| @@ -976,7 +995,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
| 976 | } | 995 | } |
| 977 | 996 | ||
| 978 | pltfm_host->clk = imx_data->clk_per; | 997 | pltfm_host->clk = imx_data->clk_per; |
| 979 | 998 | pltfm_host->clock = clk_get_rate(pltfm_host->clk); | |
| 980 | clk_prepare_enable(imx_data->clk_per); | 999 | clk_prepare_enable(imx_data->clk_per); |
| 981 | clk_prepare_enable(imx_data->clk_ipg); | 1000 | clk_prepare_enable(imx_data->clk_ipg); |
| 982 | clk_prepare_enable(imx_data->clk_ahb); | 1001 | clk_prepare_enable(imx_data->clk_ahb); |
| @@ -1009,11 +1028,18 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
| 1009 | if (esdhc_is_usdhc(imx_data)) { | 1028 | if (esdhc_is_usdhc(imx_data)) { |
| 1010 | writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL); | 1029 | writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL); |
| 1011 | host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; | 1030 | host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; |
| 1031 | host->mmc->caps |= MMC_CAP_1_8V_DDR; | ||
| 1012 | } | 1032 | } |
| 1013 | 1033 | ||
| 1014 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) | 1034 | if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) |
| 1015 | sdhci_esdhc_ops.platform_execute_tuning = | 1035 | sdhci_esdhc_ops.platform_execute_tuning = |
| 1016 | esdhc_executing_tuning; | 1036 | esdhc_executing_tuning; |
| 1037 | |||
| 1038 | if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) | ||
| 1039 | writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) | | ||
| 1040 | ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP, | ||
| 1041 | host->ioaddr + ESDHC_TUNING_CTRL); | ||
| 1042 | |||
| 1017 | boarddata = &imx_data->boarddata; | 1043 | boarddata = &imx_data->boarddata; |
| 1018 | if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { | 1044 | if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { |
| 1019 | if (!host->mmc->parent->platform_data) { | 1045 | if (!host->mmc->parent->platform_data) { |
| @@ -1053,7 +1079,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
| 1053 | break; | 1079 | break; |
| 1054 | 1080 | ||
| 1055 | case ESDHC_CD_PERMANENT: | 1081 | case ESDHC_CD_PERMANENT: |
| 1056 | host->mmc->caps = MMC_CAP_NONREMOVABLE; | 1082 | host->mmc->caps |= MMC_CAP_NONREMOVABLE; |
| 1057 | break; | 1083 | break; |
| 1058 | 1084 | ||
| 1059 | case ESDHC_CD_NONE: | 1085 | case ESDHC_CD_NONE: |
| @@ -1094,6 +1120,12 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
| 1094 | if (err) | 1120 | if (err) |
| 1095 | goto disable_clk; | 1121 | goto disable_clk; |
| 1096 | 1122 | ||
| 1123 | pm_runtime_set_active(&pdev->dev); | ||
| 1124 | pm_runtime_enable(&pdev->dev); | ||
| 1125 | pm_runtime_set_autosuspend_delay(&pdev->dev, 50); | ||
| 1126 | pm_runtime_use_autosuspend(&pdev->dev); | ||
| 1127 | pm_suspend_ignore_children(&pdev->dev, 1); | ||
| 1128 | |||
| 1097 | return 0; | 1129 | return 0; |
| 1098 | 1130 | ||
| 1099 | disable_clk: | 1131 | disable_clk: |
| @@ -1114,21 +1146,63 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev) | |||
| 1114 | 1146 | ||
| 1115 | sdhci_remove_host(host, dead); | 1147 | sdhci_remove_host(host, dead); |
| 1116 | 1148 | ||
| 1149 | pm_runtime_dont_use_autosuspend(&pdev->dev); | ||
| 1150 | pm_runtime_disable(&pdev->dev); | ||
| 1151 | |||
| 1152 | if (!IS_ENABLED(CONFIG_PM_RUNTIME)) { | ||
| 1153 | clk_disable_unprepare(imx_data->clk_per); | ||
| 1154 | clk_disable_unprepare(imx_data->clk_ipg); | ||
| 1155 | clk_disable_unprepare(imx_data->clk_ahb); | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | sdhci_pltfm_free(pdev); | ||
| 1159 | |||
| 1160 | return 0; | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | #ifdef CONFIG_PM_RUNTIME | ||
| 1164 | static int sdhci_esdhc_runtime_suspend(struct device *dev) | ||
| 1165 | { | ||
| 1166 | struct sdhci_host *host = dev_get_drvdata(dev); | ||
| 1167 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 1168 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
| 1169 | int ret; | ||
| 1170 | |||
| 1171 | ret = sdhci_runtime_suspend_host(host); | ||
| 1172 | |||
| 1117 | clk_disable_unprepare(imx_data->clk_per); | 1173 | clk_disable_unprepare(imx_data->clk_per); |
| 1118 | clk_disable_unprepare(imx_data->clk_ipg); | 1174 | clk_disable_unprepare(imx_data->clk_ipg); |
| 1119 | clk_disable_unprepare(imx_data->clk_ahb); | 1175 | clk_disable_unprepare(imx_data->clk_ahb); |
| 1120 | 1176 | ||
| 1121 | sdhci_pltfm_free(pdev); | 1177 | return ret; |
| 1178 | } | ||
| 1122 | 1179 | ||
| 1123 | return 0; | 1180 | static int sdhci_esdhc_runtime_resume(struct device *dev) |
| 1181 | { | ||
| 1182 | struct sdhci_host *host = dev_get_drvdata(dev); | ||
| 1183 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 1184 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
| 1185 | |||
| 1186 | clk_prepare_enable(imx_data->clk_per); | ||
| 1187 | clk_prepare_enable(imx_data->clk_ipg); | ||
| 1188 | clk_prepare_enable(imx_data->clk_ahb); | ||
| 1189 | |||
| 1190 | return sdhci_runtime_resume_host(host); | ||
| 1124 | } | 1191 | } |
| 1192 | #endif | ||
| 1193 | |||
| 1194 | static const struct dev_pm_ops sdhci_esdhc_pmops = { | ||
| 1195 | SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume) | ||
| 1196 | SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend, | ||
| 1197 | sdhci_esdhc_runtime_resume, NULL) | ||
| 1198 | }; | ||
| 1125 | 1199 | ||
| 1126 | static struct platform_driver sdhci_esdhc_imx_driver = { | 1200 | static struct platform_driver sdhci_esdhc_imx_driver = { |
| 1127 | .driver = { | 1201 | .driver = { |
| 1128 | .name = "sdhci-esdhc-imx", | 1202 | .name = "sdhci-esdhc-imx", |
| 1129 | .owner = THIS_MODULE, | 1203 | .owner = THIS_MODULE, |
| 1130 | .of_match_table = imx_esdhc_dt_ids, | 1204 | .of_match_table = imx_esdhc_dt_ids, |
| 1131 | .pm = SDHCI_PLTFM_PMOPS, | 1205 | .pm = &sdhci_esdhc_pmops, |
| 1132 | }, | 1206 | }, |
| 1133 | .id_table = imx_esdhc_devtype, | 1207 | .id_table = imx_esdhc_devtype, |
| 1134 | .probe = sdhci_esdhc_imx_probe, | 1208 | .probe = sdhci_esdhc_imx_probe, |
diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c new file mode 100644 index 000000000000..f7c7cf62437d --- /dev/null +++ b/drivers/mmc/host/sdhci-of-arasan.c | |||
| @@ -0,0 +1,224 @@ | |||
| 1 | /* | ||
| 2 | * Arasan Secure Digital Host Controller Interface. | ||
| 3 | * Copyright (C) 2011 - 2012 Michal Simek <monstr@monstr.eu> | ||
| 4 | * Copyright (c) 2012 Wind River Systems, Inc. | ||
| 5 | * Copyright (C) 2013 Pengutronix e.K. | ||
| 6 | * Copyright (C) 2013 Xilinx Inc. | ||
| 7 | * | ||
| 8 | * Based on sdhci-of-esdhc.c | ||
| 9 | * | ||
| 10 | * Copyright (c) 2007 Freescale Semiconductor, Inc. | ||
| 11 | * Copyright (c) 2009 MontaVista Software, Inc. | ||
| 12 | * | ||
| 13 | * Authors: Xiaobo Xie <X.Xie@freescale.com> | ||
| 14 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 15 | * | ||
| 16 | * This program is free software; you can redistribute it and/or modify | ||
| 17 | * it under the terms of the GNU General Public License as published by | ||
| 18 | * the Free Software Foundation; either version 2 of the License, or (at | ||
| 19 | * your option) any later version. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/module.h> | ||
| 23 | #include "sdhci-pltfm.h" | ||
| 24 | |||
| 25 | #define SDHCI_ARASAN_CLK_CTRL_OFFSET 0x2c | ||
| 26 | |||
| 27 | #define CLK_CTRL_TIMEOUT_SHIFT 16 | ||
| 28 | #define CLK_CTRL_TIMEOUT_MASK (0xf << CLK_CTRL_TIMEOUT_SHIFT) | ||
| 29 | #define CLK_CTRL_TIMEOUT_MIN_EXP 13 | ||
| 30 | |||
| 31 | /** | ||
| 32 | * struct sdhci_arasan_data | ||
| 33 | * @clk_ahb: Pointer to the AHB clock | ||
| 34 | */ | ||
| 35 | struct sdhci_arasan_data { | ||
| 36 | struct clk *clk_ahb; | ||
| 37 | }; | ||
| 38 | |||
| 39 | static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host) | ||
| 40 | { | ||
| 41 | u32 div; | ||
| 42 | unsigned long freq; | ||
| 43 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 44 | |||
| 45 | div = readl(host->ioaddr + SDHCI_ARASAN_CLK_CTRL_OFFSET); | ||
| 46 | div = (div & CLK_CTRL_TIMEOUT_MASK) >> CLK_CTRL_TIMEOUT_SHIFT; | ||
| 47 | |||
| 48 | freq = clk_get_rate(pltfm_host->clk); | ||
| 49 | freq /= 1 << (CLK_CTRL_TIMEOUT_MIN_EXP + div); | ||
| 50 | |||
| 51 | return freq; | ||
| 52 | } | ||
| 53 | |||
| 54 | static struct sdhci_ops sdhci_arasan_ops = { | ||
| 55 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, | ||
| 56 | .get_timeout_clock = sdhci_arasan_get_timeout_clock, | ||
| 57 | }; | ||
| 58 | |||
| 59 | static struct sdhci_pltfm_data sdhci_arasan_pdata = { | ||
| 60 | .ops = &sdhci_arasan_ops, | ||
| 61 | }; | ||
| 62 | |||
| 63 | #ifdef CONFIG_PM_SLEEP | ||
| 64 | /** | ||
| 65 | * sdhci_arasan_suspend - Suspend method for the driver | ||
| 66 | * @dev: Address of the device structure | ||
| 67 | * Returns 0 on success and error value on error | ||
| 68 | * | ||
| 69 | * Put the device in a low power state. | ||
| 70 | */ | ||
| 71 | static int sdhci_arasan_suspend(struct device *dev) | ||
| 72 | { | ||
| 73 | struct platform_device *pdev = to_platform_device(dev); | ||
| 74 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
| 75 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 76 | struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; | ||
| 77 | int ret; | ||
| 78 | |||
| 79 | ret = sdhci_suspend_host(host); | ||
| 80 | if (ret) | ||
| 81 | return ret; | ||
| 82 | |||
| 83 | clk_disable(pltfm_host->clk); | ||
| 84 | clk_disable(sdhci_arasan->clk_ahb); | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | /** | ||
| 90 | * sdhci_arasan_resume - Resume method for the driver | ||
| 91 | * @dev: Address of the device structure | ||
| 92 | * Returns 0 on success and error value on error | ||
| 93 | * | ||
| 94 | * Resume operation after suspend | ||
| 95 | */ | ||
| 96 | static int sdhci_arasan_resume(struct device *dev) | ||
| 97 | { | ||
| 98 | struct platform_device *pdev = to_platform_device(dev); | ||
| 99 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
| 100 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 101 | struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; | ||
| 102 | int ret; | ||
| 103 | |||
| 104 | ret = clk_enable(sdhci_arasan->clk_ahb); | ||
| 105 | if (ret) { | ||
| 106 | dev_err(dev, "Cannot enable AHB clock.\n"); | ||
| 107 | return ret; | ||
| 108 | } | ||
| 109 | |||
| 110 | ret = clk_enable(pltfm_host->clk); | ||
| 111 | if (ret) { | ||
| 112 | dev_err(dev, "Cannot enable SD clock.\n"); | ||
| 113 | clk_disable(sdhci_arasan->clk_ahb); | ||
| 114 | return ret; | ||
| 115 | } | ||
| 116 | |||
| 117 | return sdhci_resume_host(host); | ||
| 118 | } | ||
| 119 | #endif /* ! CONFIG_PM_SLEEP */ | ||
| 120 | |||
| 121 | static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend, | ||
| 122 | sdhci_arasan_resume); | ||
| 123 | |||
| 124 | static int sdhci_arasan_probe(struct platform_device *pdev) | ||
| 125 | { | ||
| 126 | int ret; | ||
| 127 | struct clk *clk_xin; | ||
| 128 | struct sdhci_host *host; | ||
| 129 | struct sdhci_pltfm_host *pltfm_host; | ||
| 130 | struct sdhci_arasan_data *sdhci_arasan; | ||
| 131 | |||
| 132 | sdhci_arasan = devm_kzalloc(&pdev->dev, sizeof(*sdhci_arasan), | ||
| 133 | GFP_KERNEL); | ||
| 134 | if (!sdhci_arasan) | ||
| 135 | return -ENOMEM; | ||
| 136 | |||
| 137 | sdhci_arasan->clk_ahb = devm_clk_get(&pdev->dev, "clk_ahb"); | ||
| 138 | if (IS_ERR(sdhci_arasan->clk_ahb)) { | ||
| 139 | dev_err(&pdev->dev, "clk_ahb clock not found.\n"); | ||
| 140 | return PTR_ERR(sdhci_arasan->clk_ahb); | ||
| 141 | } | ||
| 142 | |||
| 143 | clk_xin = devm_clk_get(&pdev->dev, "clk_xin"); | ||
| 144 | if (IS_ERR(clk_xin)) { | ||
| 145 | dev_err(&pdev->dev, "clk_xin clock not found.\n"); | ||
| 146 | return PTR_ERR(clk_xin); | ||
| 147 | } | ||
| 148 | |||
| 149 | ret = clk_prepare_enable(sdhci_arasan->clk_ahb); | ||
| 150 | if (ret) { | ||
| 151 | dev_err(&pdev->dev, "Unable to enable AHB clock.\n"); | ||
| 152 | return ret; | ||
| 153 | } | ||
| 154 | |||
| 155 | ret = clk_prepare_enable(clk_xin); | ||
| 156 | if (ret) { | ||
| 157 | dev_err(&pdev->dev, "Unable to enable SD clock.\n"); | ||
| 158 | goto clk_dis_ahb; | ||
| 159 | } | ||
| 160 | |||
| 161 | host = sdhci_pltfm_init(pdev, &sdhci_arasan_pdata, 0); | ||
| 162 | if (IS_ERR(host)) { | ||
| 163 | ret = PTR_ERR(host); | ||
| 164 | dev_err(&pdev->dev, "platform init failed (%u)\n", ret); | ||
| 165 | goto clk_disable_all; | ||
| 166 | } | ||
| 167 | |||
| 168 | sdhci_get_of_property(pdev); | ||
| 169 | pltfm_host = sdhci_priv(host); | ||
| 170 | pltfm_host->priv = sdhci_arasan; | ||
| 171 | pltfm_host->clk = clk_xin; | ||
| 172 | |||
| 173 | ret = sdhci_add_host(host); | ||
| 174 | if (ret) { | ||
| 175 | dev_err(&pdev->dev, "platform register failed (%u)\n", ret); | ||
| 176 | goto err_pltfm_free; | ||
| 177 | } | ||
| 178 | |||
| 179 | return 0; | ||
| 180 | |||
| 181 | err_pltfm_free: | ||
| 182 | sdhci_pltfm_free(pdev); | ||
| 183 | clk_disable_all: | ||
| 184 | clk_disable_unprepare(clk_xin); | ||
| 185 | clk_dis_ahb: | ||
| 186 | clk_disable_unprepare(sdhci_arasan->clk_ahb); | ||
| 187 | |||
| 188 | return ret; | ||
| 189 | } | ||
| 190 | |||
| 191 | static int sdhci_arasan_remove(struct platform_device *pdev) | ||
| 192 | { | ||
| 193 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
| 194 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 195 | struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; | ||
| 196 | |||
| 197 | clk_disable_unprepare(pltfm_host->clk); | ||
| 198 | clk_disable_unprepare(sdhci_arasan->clk_ahb); | ||
| 199 | |||
| 200 | return sdhci_pltfm_unregister(pdev); | ||
| 201 | } | ||
| 202 | |||
| 203 | static const struct of_device_id sdhci_arasan_of_match[] = { | ||
| 204 | { .compatible = "arasan,sdhci-8.9a" }, | ||
| 205 | { } | ||
| 206 | }; | ||
| 207 | MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match); | ||
| 208 | |||
| 209 | static struct platform_driver sdhci_arasan_driver = { | ||
| 210 | .driver = { | ||
| 211 | .name = "sdhci-arasan", | ||
| 212 | .owner = THIS_MODULE, | ||
| 213 | .of_match_table = sdhci_arasan_of_match, | ||
| 214 | .pm = &sdhci_arasan_dev_pm_ops, | ||
| 215 | }, | ||
| 216 | .probe = sdhci_arasan_probe, | ||
| 217 | .remove = sdhci_arasan_remove, | ||
| 218 | }; | ||
| 219 | |||
| 220 | module_platform_driver(sdhci_arasan_driver); | ||
| 221 | |||
| 222 | MODULE_DESCRIPTION("Driver for the Arasan SDHCI Controller"); | ||
| 223 | MODULE_AUTHOR("Soeren Brinkmann <soren.brinkmann@xilinx.com>"); | ||
| 224 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c new file mode 100644 index 000000000000..f49666bcc52a --- /dev/null +++ b/drivers/mmc/host/sdhci-pci-o2micro.c | |||
| @@ -0,0 +1,321 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 BayHub Technology Ltd. | ||
| 3 | * | ||
| 4 | * Authors: Peter Guo <peter.guo@bayhubtech.com> | ||
| 5 | * Adam Lee <adam.lee@canonical.com> | ||
| 6 | * | ||
| 7 | * This software is licensed under the terms of the GNU General Public | ||
| 8 | * License version 2, as published by the Free Software Foundation, and | ||
| 9 | * may be copied, distributed, and modified under those terms. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/pci.h> | ||
| 19 | |||
| 20 | #include "sdhci.h" | ||
| 21 | #include "sdhci-pci.h" | ||
| 22 | #include "sdhci-pci-o2micro.h" | ||
| 23 | |||
| 24 | void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip) | ||
| 25 | { | ||
| 26 | u32 scratch_32; | ||
| 27 | int ret; | ||
| 28 | /* Improve write performance for SD3.0 */ | ||
| 29 | ret = pci_read_config_dword(chip->pdev, O2_SD_DEV_CTRL, &scratch_32); | ||
| 30 | if (ret) | ||
| 31 | return; | ||
| 32 | scratch_32 &= ~((1 << 12) | (1 << 13) | (1 << 14)); | ||
| 33 | pci_write_config_dword(chip->pdev, O2_SD_DEV_CTRL, scratch_32); | ||
| 34 | |||
| 35 | /* Enable Link abnormal reset generating Reset */ | ||
| 36 | ret = pci_read_config_dword(chip->pdev, O2_SD_MISC_REG5, &scratch_32); | ||
| 37 | if (ret) | ||
| 38 | return; | ||
| 39 | scratch_32 &= ~((1 << 19) | (1 << 11)); | ||
| 40 | scratch_32 |= (1 << 10); | ||
| 41 | pci_write_config_dword(chip->pdev, O2_SD_MISC_REG5, scratch_32); | ||
| 42 | |||
| 43 | /* set card power over current protection */ | ||
| 44 | ret = pci_read_config_dword(chip->pdev, O2_SD_TEST_REG, &scratch_32); | ||
| 45 | if (ret) | ||
| 46 | return; | ||
| 47 | scratch_32 |= (1 << 4); | ||
| 48 | pci_write_config_dword(chip->pdev, O2_SD_TEST_REG, scratch_32); | ||
| 49 | |||
| 50 | /* adjust the output delay for SD mode */ | ||
| 51 | pci_write_config_dword(chip->pdev, O2_SD_DELAY_CTRL, 0x00002492); | ||
| 52 | |||
| 53 | /* Set the output voltage setting of Aux 1.2v LDO */ | ||
| 54 | ret = pci_read_config_dword(chip->pdev, O2_SD_LD0_CTRL, &scratch_32); | ||
| 55 | if (ret) | ||
| 56 | return; | ||
| 57 | scratch_32 &= ~(3 << 12); | ||
| 58 | pci_write_config_dword(chip->pdev, O2_SD_LD0_CTRL, scratch_32); | ||
| 59 | |||
| 60 | /* Set Max power supply capability of SD host */ | ||
| 61 | ret = pci_read_config_dword(chip->pdev, O2_SD_CAP_REG0, &scratch_32); | ||
| 62 | if (ret) | ||
| 63 | return; | ||
| 64 | scratch_32 &= ~(0x01FE); | ||
| 65 | scratch_32 |= 0x00CC; | ||
| 66 | pci_write_config_dword(chip->pdev, O2_SD_CAP_REG0, scratch_32); | ||
| 67 | /* Set DLL Tuning Window */ | ||
| 68 | ret = pci_read_config_dword(chip->pdev, | ||
| 69 | O2_SD_TUNING_CTRL, &scratch_32); | ||
| 70 | if (ret) | ||
| 71 | return; | ||
| 72 | scratch_32 &= ~(0x000000FF); | ||
| 73 | scratch_32 |= 0x00000066; | ||
| 74 | pci_write_config_dword(chip->pdev, O2_SD_TUNING_CTRL, scratch_32); | ||
| 75 | |||
| 76 | /* Set UHS2 T_EIDLE */ | ||
| 77 | ret = pci_read_config_dword(chip->pdev, | ||
| 78 | O2_SD_UHS2_L1_CTRL, &scratch_32); | ||
| 79 | if (ret) | ||
| 80 | return; | ||
| 81 | scratch_32 &= ~(0x000000FC); | ||
| 82 | scratch_32 |= 0x00000084; | ||
| 83 | pci_write_config_dword(chip->pdev, O2_SD_UHS2_L1_CTRL, scratch_32); | ||
| 84 | |||
| 85 | /* Set UHS2 Termination */ | ||
| 86 | ret = pci_read_config_dword(chip->pdev, O2_SD_FUNC_REG3, &scratch_32); | ||
| 87 | if (ret) | ||
| 88 | return; | ||
| 89 | scratch_32 &= ~((1 << 21) | (1 << 30)); | ||
| 90 | |||
| 91 | /* Set RTD3 function disabled */ | ||
| 92 | scratch_32 |= ((1 << 29) | (1 << 28)); | ||
| 93 | pci_write_config_dword(chip->pdev, O2_SD_FUNC_REG3, scratch_32); | ||
| 94 | |||
| 95 | /* Set L1 Entrance Timer */ | ||
| 96 | ret = pci_read_config_dword(chip->pdev, O2_SD_CAPS, &scratch_32); | ||
| 97 | if (ret) | ||
| 98 | return; | ||
| 99 | scratch_32 &= ~(0xf0000000); | ||
| 100 | scratch_32 |= 0x30000000; | ||
| 101 | pci_write_config_dword(chip->pdev, O2_SD_CAPS, scratch_32); | ||
| 102 | |||
| 103 | ret = pci_read_config_dword(chip->pdev, | ||
| 104 | O2_SD_MISC_CTRL4, &scratch_32); | ||
| 105 | if (ret) | ||
| 106 | return; | ||
| 107 | scratch_32 &= ~(0x000f0000); | ||
| 108 | scratch_32 |= 0x00080000; | ||
| 109 | pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL4, scratch_32); | ||
| 110 | } | ||
| 111 | EXPORT_SYMBOL_GPL(sdhci_pci_o2_fujin2_pci_init); | ||
| 112 | |||
| 113 | int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) | ||
| 114 | { | ||
| 115 | struct sdhci_pci_chip *chip; | ||
| 116 | struct sdhci_host *host; | ||
| 117 | u32 reg; | ||
| 118 | |||
| 119 | chip = slot->chip; | ||
| 120 | host = slot->host; | ||
| 121 | switch (chip->pdev->device) { | ||
| 122 | case PCI_DEVICE_ID_O2_SDS0: | ||
| 123 | case PCI_DEVICE_ID_O2_SEABIRD0: | ||
| 124 | case PCI_DEVICE_ID_O2_SEABIRD1: | ||
| 125 | case PCI_DEVICE_ID_O2_SDS1: | ||
| 126 | case PCI_DEVICE_ID_O2_FUJIN2: | ||
| 127 | reg = sdhci_readl(host, O2_SD_VENDOR_SETTING); | ||
| 128 | if (reg & 0x1) | ||
| 129 | host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; | ||
| 130 | |||
| 131 | if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2) | ||
| 132 | break; | ||
| 133 | /* set dll watch dog timer */ | ||
| 134 | reg = sdhci_readl(host, O2_SD_VENDOR_SETTING2); | ||
| 135 | reg |= (1 << 12); | ||
| 136 | sdhci_writel(host, reg, O2_SD_VENDOR_SETTING2); | ||
| 137 | |||
| 138 | break; | ||
| 139 | default: | ||
| 140 | break; | ||
| 141 | } | ||
| 142 | |||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | EXPORT_SYMBOL_GPL(sdhci_pci_o2_probe_slot); | ||
| 146 | |||
| 147 | int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) | ||
| 148 | { | ||
| 149 | int ret; | ||
| 150 | u8 scratch; | ||
| 151 | u32 scratch_32; | ||
| 152 | |||
| 153 | switch (chip->pdev->device) { | ||
| 154 | case PCI_DEVICE_ID_O2_8220: | ||
| 155 | case PCI_DEVICE_ID_O2_8221: | ||
| 156 | case PCI_DEVICE_ID_O2_8320: | ||
| 157 | case PCI_DEVICE_ID_O2_8321: | ||
| 158 | /* This extra setup is required due to broken ADMA. */ | ||
| 159 | ret = pci_read_config_byte(chip->pdev, | ||
| 160 | O2_SD_LOCK_WP, &scratch); | ||
| 161 | if (ret) | ||
| 162 | return ret; | ||
| 163 | scratch &= 0x7f; | ||
| 164 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
| 165 | |||
| 166 | /* Set Multi 3 to VCC3V# */ | ||
| 167 | pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08); | ||
| 168 | |||
| 169 | /* Disable CLK_REQ# support after media DET */ | ||
| 170 | ret = pci_read_config_byte(chip->pdev, | ||
| 171 | O2_SD_CLKREQ, &scratch); | ||
| 172 | if (ret) | ||
| 173 | return ret; | ||
| 174 | scratch |= 0x20; | ||
| 175 | pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch); | ||
| 176 | |||
| 177 | /* Choose capabilities, enable SDMA. We have to write 0x01 | ||
| 178 | * to the capabilities register first to unlock it. | ||
| 179 | */ | ||
| 180 | ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch); | ||
| 181 | if (ret) | ||
| 182 | return ret; | ||
| 183 | scratch |= 0x01; | ||
| 184 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch); | ||
| 185 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73); | ||
| 186 | |||
| 187 | /* Disable ADMA1/2 */ | ||
| 188 | pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39); | ||
| 189 | pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08); | ||
| 190 | |||
| 191 | /* Disable the infinite transfer mode */ | ||
| 192 | ret = pci_read_config_byte(chip->pdev, | ||
| 193 | O2_SD_INF_MOD, &scratch); | ||
| 194 | if (ret) | ||
| 195 | return ret; | ||
| 196 | scratch |= 0x08; | ||
| 197 | pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch); | ||
| 198 | |||
| 199 | /* Lock WP */ | ||
| 200 | ret = pci_read_config_byte(chip->pdev, | ||
| 201 | O2_SD_LOCK_WP, &scratch); | ||
| 202 | if (ret) | ||
| 203 | return ret; | ||
| 204 | scratch |= 0x80; | ||
| 205 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
| 206 | break; | ||
| 207 | case PCI_DEVICE_ID_O2_SDS0: | ||
| 208 | case PCI_DEVICE_ID_O2_SDS1: | ||
| 209 | case PCI_DEVICE_ID_O2_FUJIN2: | ||
| 210 | /* UnLock WP */ | ||
| 211 | ret = pci_read_config_byte(chip->pdev, | ||
| 212 | O2_SD_LOCK_WP, &scratch); | ||
| 213 | if (ret) | ||
| 214 | return ret; | ||
| 215 | |||
| 216 | scratch &= 0x7f; | ||
| 217 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
| 218 | |||
| 219 | /* Set timeout CLK */ | ||
| 220 | ret = pci_read_config_dword(chip->pdev, | ||
| 221 | O2_SD_CLK_SETTING, &scratch_32); | ||
| 222 | if (ret) | ||
| 223 | return ret; | ||
| 224 | |||
| 225 | scratch_32 &= ~(0xFF00); | ||
| 226 | scratch_32 |= 0x07E0C800; | ||
| 227 | pci_write_config_dword(chip->pdev, | ||
| 228 | O2_SD_CLK_SETTING, scratch_32); | ||
| 229 | |||
| 230 | ret = pci_read_config_dword(chip->pdev, | ||
| 231 | O2_SD_CLKREQ, &scratch_32); | ||
| 232 | if (ret) | ||
| 233 | return ret; | ||
| 234 | scratch_32 |= 0x3; | ||
| 235 | pci_write_config_dword(chip->pdev, O2_SD_CLKREQ, scratch_32); | ||
| 236 | |||
| 237 | ret = pci_read_config_dword(chip->pdev, | ||
| 238 | O2_SD_PLL_SETTING, &scratch_32); | ||
| 239 | if (ret) | ||
| 240 | return ret; | ||
| 241 | |||
| 242 | scratch_32 &= ~(0x1F3F070E); | ||
| 243 | scratch_32 |= 0x18270106; | ||
| 244 | pci_write_config_dword(chip->pdev, | ||
| 245 | O2_SD_PLL_SETTING, scratch_32); | ||
| 246 | |||
| 247 | /* Disable UHS1 funciton */ | ||
| 248 | ret = pci_read_config_dword(chip->pdev, | ||
| 249 | O2_SD_CAP_REG2, &scratch_32); | ||
| 250 | if (ret) | ||
| 251 | return ret; | ||
| 252 | scratch_32 &= ~(0xE0); | ||
| 253 | pci_write_config_dword(chip->pdev, | ||
| 254 | O2_SD_CAP_REG2, scratch_32); | ||
| 255 | |||
| 256 | if (chip->pdev->device == PCI_DEVICE_ID_O2_FUJIN2) | ||
| 257 | sdhci_pci_o2_fujin2_pci_init(chip); | ||
| 258 | |||
| 259 | /* Lock WP */ | ||
| 260 | ret = pci_read_config_byte(chip->pdev, | ||
| 261 | O2_SD_LOCK_WP, &scratch); | ||
| 262 | if (ret) | ||
| 263 | return ret; | ||
| 264 | scratch |= 0x80; | ||
| 265 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
| 266 | break; | ||
| 267 | case PCI_DEVICE_ID_O2_SEABIRD0: | ||
| 268 | case PCI_DEVICE_ID_O2_SEABIRD1: | ||
| 269 | /* UnLock WP */ | ||
| 270 | ret = pci_read_config_byte(chip->pdev, | ||
| 271 | O2_SD_LOCK_WP, &scratch); | ||
| 272 | if (ret) | ||
| 273 | return ret; | ||
| 274 | |||
| 275 | scratch &= 0x7f; | ||
| 276 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
| 277 | |||
| 278 | ret = pci_read_config_dword(chip->pdev, | ||
| 279 | O2_SD_FUNC_REG0, &scratch_32); | ||
| 280 | |||
| 281 | if ((scratch_32 & 0xff000000) == 0x01000000) { | ||
| 282 | scratch_32 &= 0x0000FFFF; | ||
| 283 | scratch_32 |= 0x1F340000; | ||
| 284 | |||
| 285 | pci_write_config_dword(chip->pdev, | ||
| 286 | O2_SD_PLL_SETTING, scratch_32); | ||
| 287 | } else { | ||
| 288 | scratch_32 &= 0x0000FFFF; | ||
| 289 | scratch_32 |= 0x2c280000; | ||
| 290 | |||
| 291 | pci_write_config_dword(chip->pdev, | ||
| 292 | O2_SD_PLL_SETTING, scratch_32); | ||
| 293 | |||
| 294 | ret = pci_read_config_dword(chip->pdev, | ||
| 295 | O2_SD_FUNC_REG4, | ||
| 296 | &scratch_32); | ||
| 297 | scratch_32 |= (1 << 22); | ||
| 298 | pci_write_config_dword(chip->pdev, | ||
| 299 | O2_SD_FUNC_REG4, scratch_32); | ||
| 300 | } | ||
| 301 | |||
| 302 | /* Lock WP */ | ||
| 303 | ret = pci_read_config_byte(chip->pdev, | ||
| 304 | O2_SD_LOCK_WP, &scratch); | ||
| 305 | if (ret) | ||
| 306 | return ret; | ||
| 307 | scratch |= 0x80; | ||
| 308 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
| 309 | break; | ||
| 310 | } | ||
| 311 | |||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | EXPORT_SYMBOL_GPL(sdhci_pci_o2_probe); | ||
| 315 | |||
| 316 | int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip) | ||
| 317 | { | ||
| 318 | sdhci_pci_o2_probe(chip); | ||
| 319 | return 0; | ||
| 320 | } | ||
| 321 | EXPORT_SYMBOL_GPL(sdhci_pci_o2_resume); | ||
diff --git a/drivers/mmc/host/sdhci-pci-o2micro.h b/drivers/mmc/host/sdhci-pci-o2micro.h new file mode 100644 index 000000000000..dbec4c933488 --- /dev/null +++ b/drivers/mmc/host/sdhci-pci-o2micro.h | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 BayHub Technology Ltd. | ||
| 3 | * | ||
| 4 | * Authors: Peter Guo <peter.guo@bayhubtech.com> | ||
| 5 | * Adam Lee <adam.lee@canonical.com> | ||
| 6 | * | ||
| 7 | * This software is licensed under the terms of the GNU General Public | ||
| 8 | * License version 2, as published by the Free Software Foundation, and | ||
| 9 | * may be copied, distributed, and modified under those terms. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef __SDHCI_PCI_O2MICRO_H | ||
| 19 | #define __SDHCI_PCI_O2MICRO_H | ||
| 20 | |||
| 21 | #include "sdhci-pci.h" | ||
| 22 | |||
| 23 | /* | ||
| 24 | * O2Micro device IDs | ||
| 25 | */ | ||
| 26 | |||
| 27 | #define PCI_DEVICE_ID_O2_SDS0 0x8420 | ||
| 28 | #define PCI_DEVICE_ID_O2_SDS1 0x8421 | ||
| 29 | #define PCI_DEVICE_ID_O2_FUJIN2 0x8520 | ||
| 30 | #define PCI_DEVICE_ID_O2_SEABIRD0 0x8620 | ||
| 31 | #define PCI_DEVICE_ID_O2_SEABIRD1 0x8621 | ||
| 32 | |||
| 33 | /* | ||
| 34 | * O2Micro device registers | ||
| 35 | */ | ||
| 36 | |||
| 37 | #define O2_SD_MISC_REG5 0x64 | ||
| 38 | #define O2_SD_LD0_CTRL 0x68 | ||
| 39 | #define O2_SD_DEV_CTRL 0x88 | ||
| 40 | #define O2_SD_LOCK_WP 0xD3 | ||
| 41 | #define O2_SD_TEST_REG 0xD4 | ||
| 42 | #define O2_SD_FUNC_REG0 0xDC | ||
| 43 | #define O2_SD_MULTI_VCC3V 0xEE | ||
| 44 | #define O2_SD_CLKREQ 0xEC | ||
| 45 | #define O2_SD_CAPS 0xE0 | ||
| 46 | #define O2_SD_ADMA1 0xE2 | ||
| 47 | #define O2_SD_ADMA2 0xE7 | ||
| 48 | #define O2_SD_INF_MOD 0xF1 | ||
| 49 | #define O2_SD_MISC_CTRL4 0xFC | ||
| 50 | #define O2_SD_TUNING_CTRL 0x300 | ||
| 51 | #define O2_SD_PLL_SETTING 0x304 | ||
| 52 | #define O2_SD_CLK_SETTING 0x328 | ||
| 53 | #define O2_SD_CAP_REG2 0x330 | ||
| 54 | #define O2_SD_CAP_REG0 0x334 | ||
| 55 | #define O2_SD_UHS1_CAP_SETTING 0x33C | ||
| 56 | #define O2_SD_DELAY_CTRL 0x350 | ||
| 57 | #define O2_SD_UHS2_L1_CTRL 0x35C | ||
| 58 | #define O2_SD_FUNC_REG3 0x3E0 | ||
| 59 | #define O2_SD_FUNC_REG4 0x3E4 | ||
| 60 | |||
| 61 | #define O2_SD_VENDOR_SETTING 0x110 | ||
| 62 | #define O2_SD_VENDOR_SETTING2 0x1C8 | ||
| 63 | |||
| 64 | extern void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip); | ||
| 65 | |||
| 66 | extern int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot); | ||
| 67 | |||
| 68 | extern int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip); | ||
| 69 | |||
| 70 | extern int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip); | ||
| 71 | |||
| 72 | #endif /* __SDHCI_PCI_O2MICRO_H */ | ||
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 8f753811fc7a..0955777b6c7e 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -27,79 +27,8 @@ | |||
| 27 | #include <linux/mmc/sdhci-pci-data.h> | 27 | #include <linux/mmc/sdhci-pci-data.h> |
| 28 | 28 | ||
| 29 | #include "sdhci.h" | 29 | #include "sdhci.h" |
| 30 | 30 | #include "sdhci-pci.h" | |
| 31 | /* | 31 | #include "sdhci-pci-o2micro.h" |
| 32 | * PCI device IDs | ||
| 33 | */ | ||
| 34 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 | ||
| 35 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a | ||
| 36 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC 0x0f14 | ||
| 37 | #define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 | ||
| 38 | #define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 | ||
| 39 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC2 0x0f50 | ||
| 40 | #define PCI_DEVICE_ID_INTEL_MRFL_MMC 0x1190 | ||
| 41 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO0 0x08f9 | ||
| 42 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO1 0x08fa | ||
| 43 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO2 0x08fb | ||
| 44 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC0 0x08e5 | ||
| 45 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC1 0x08e6 | ||
| 46 | |||
| 47 | /* | ||
| 48 | * PCI registers | ||
| 49 | */ | ||
| 50 | |||
| 51 | #define PCI_SDHCI_IFPIO 0x00 | ||
| 52 | #define PCI_SDHCI_IFDMA 0x01 | ||
| 53 | #define PCI_SDHCI_IFVENDOR 0x02 | ||
| 54 | |||
| 55 | #define PCI_SLOT_INFO 0x40 /* 8 bits */ | ||
| 56 | #define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) | ||
| 57 | #define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 | ||
| 58 | |||
| 59 | #define MAX_SLOTS 8 | ||
| 60 | |||
| 61 | struct sdhci_pci_chip; | ||
| 62 | struct sdhci_pci_slot; | ||
| 63 | |||
| 64 | struct sdhci_pci_fixes { | ||
| 65 | unsigned int quirks; | ||
| 66 | unsigned int quirks2; | ||
| 67 | bool allow_runtime_pm; | ||
| 68 | |||
| 69 | int (*probe) (struct sdhci_pci_chip *); | ||
| 70 | |||
| 71 | int (*probe_slot) (struct sdhci_pci_slot *); | ||
| 72 | void (*remove_slot) (struct sdhci_pci_slot *, int); | ||
| 73 | |||
| 74 | int (*suspend) (struct sdhci_pci_chip *); | ||
| 75 | int (*resume) (struct sdhci_pci_chip *); | ||
| 76 | }; | ||
| 77 | |||
| 78 | struct sdhci_pci_slot { | ||
| 79 | struct sdhci_pci_chip *chip; | ||
| 80 | struct sdhci_host *host; | ||
| 81 | struct sdhci_pci_data *data; | ||
| 82 | |||
| 83 | int pci_bar; | ||
| 84 | int rst_n_gpio; | ||
| 85 | int cd_gpio; | ||
| 86 | int cd_irq; | ||
| 87 | |||
| 88 | void (*hw_reset)(struct sdhci_host *host); | ||
| 89 | }; | ||
| 90 | |||
| 91 | struct sdhci_pci_chip { | ||
| 92 | struct pci_dev *pdev; | ||
| 93 | |||
| 94 | unsigned int quirks; | ||
| 95 | unsigned int quirks2; | ||
| 96 | bool allow_runtime_pm; | ||
| 97 | const struct sdhci_pci_fixes *fixes; | ||
| 98 | |||
| 99 | int num_slots; /* Slots on controller */ | ||
| 100 | struct sdhci_pci_slot *slots[MAX_SLOTS]; /* Pointers to host slots */ | ||
| 101 | }; | ||
| 102 | |||
| 103 | 32 | ||
| 104 | /*****************************************************************************\ | 33 | /*****************************************************************************\ |
| 105 | * * | 34 | * * |
| @@ -296,6 +225,7 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = { | |||
| 296 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { | 225 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { |
| 297 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 226 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
| 298 | .allow_runtime_pm = true, | 227 | .allow_runtime_pm = true, |
| 228 | .own_cd_for_runtime_pm = true, | ||
| 299 | }; | 229 | }; |
| 300 | 230 | ||
| 301 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = { | 231 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = { |
| @@ -360,6 +290,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { | |||
| 360 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { | 290 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { |
| 361 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, | 291 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, |
| 362 | .allow_runtime_pm = true, | 292 | .allow_runtime_pm = true, |
| 293 | .own_cd_for_runtime_pm = true, | ||
| 363 | }; | 294 | }; |
| 364 | 295 | ||
| 365 | /* Define Host controllers for Intel Merrifield platform */ | 296 | /* Define Host controllers for Intel Merrifield platform */ |
| @@ -381,6 +312,7 @@ static int intel_mrfl_mmc_probe_slot(struct sdhci_pci_slot *slot) | |||
| 381 | 312 | ||
| 382 | static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = { | 313 | static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = { |
| 383 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 314 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
| 315 | .quirks2 = SDHCI_QUIRK2_BROKEN_HS200, | ||
| 384 | .probe_slot = intel_mrfl_mmc_probe_slot, | 316 | .probe_slot = intel_mrfl_mmc_probe_slot, |
| 385 | }; | 317 | }; |
| 386 | 318 | ||
| @@ -393,65 +325,6 @@ static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = { | |||
| 393 | #define O2_SD_ADMA2 0xE7 | 325 | #define O2_SD_ADMA2 0xE7 |
| 394 | #define O2_SD_INF_MOD 0xF1 | 326 | #define O2_SD_INF_MOD 0xF1 |
| 395 | 327 | ||
| 396 | static int o2_probe(struct sdhci_pci_chip *chip) | ||
| 397 | { | ||
| 398 | int ret; | ||
| 399 | u8 scratch; | ||
| 400 | |||
| 401 | switch (chip->pdev->device) { | ||
| 402 | case PCI_DEVICE_ID_O2_8220: | ||
| 403 | case PCI_DEVICE_ID_O2_8221: | ||
| 404 | case PCI_DEVICE_ID_O2_8320: | ||
| 405 | case PCI_DEVICE_ID_O2_8321: | ||
| 406 | /* This extra setup is required due to broken ADMA. */ | ||
| 407 | ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | ||
| 408 | if (ret) | ||
| 409 | return ret; | ||
| 410 | scratch &= 0x7f; | ||
| 411 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
| 412 | |||
| 413 | /* Set Multi 3 to VCC3V# */ | ||
| 414 | pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08); | ||
| 415 | |||
| 416 | /* Disable CLK_REQ# support after media DET */ | ||
| 417 | ret = pci_read_config_byte(chip->pdev, O2_SD_CLKREQ, &scratch); | ||
| 418 | if (ret) | ||
| 419 | return ret; | ||
| 420 | scratch |= 0x20; | ||
| 421 | pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch); | ||
| 422 | |||
| 423 | /* Choose capabilities, enable SDMA. We have to write 0x01 | ||
| 424 | * to the capabilities register first to unlock it. | ||
| 425 | */ | ||
| 426 | ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch); | ||
| 427 | if (ret) | ||
| 428 | return ret; | ||
| 429 | scratch |= 0x01; | ||
| 430 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch); | ||
| 431 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73); | ||
| 432 | |||
| 433 | /* Disable ADMA1/2 */ | ||
| 434 | pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39); | ||
| 435 | pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08); | ||
| 436 | |||
| 437 | /* Disable the infinite transfer mode */ | ||
| 438 | ret = pci_read_config_byte(chip->pdev, O2_SD_INF_MOD, &scratch); | ||
| 439 | if (ret) | ||
| 440 | return ret; | ||
| 441 | scratch |= 0x08; | ||
| 442 | pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch); | ||
| 443 | |||
| 444 | /* Lock WP */ | ||
| 445 | ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | ||
| 446 | if (ret) | ||
| 447 | return ret; | ||
| 448 | scratch |= 0x80; | ||
| 449 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
| 450 | } | ||
| 451 | |||
| 452 | return 0; | ||
| 453 | } | ||
| 454 | |||
| 455 | static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) | 328 | static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) |
| 456 | { | 329 | { |
| 457 | u8 scratch; | 330 | u8 scratch; |
| @@ -642,7 +515,10 @@ static int jmicron_resume(struct sdhci_pci_chip *chip) | |||
| 642 | } | 515 | } |
| 643 | 516 | ||
| 644 | static const struct sdhci_pci_fixes sdhci_o2 = { | 517 | static const struct sdhci_pci_fixes sdhci_o2 = { |
| 645 | .probe = o2_probe, | 518 | .probe = sdhci_pci_o2_probe, |
| 519 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | ||
| 520 | .probe_slot = sdhci_pci_o2_probe_slot, | ||
| 521 | .resume = sdhci_pci_o2_resume, | ||
| 646 | }; | 522 | }; |
| 647 | 523 | ||
| 648 | static const struct sdhci_pci_fixes sdhci_jmicron = { | 524 | static const struct sdhci_pci_fixes sdhci_jmicron = { |
| @@ -1055,6 +931,46 @@ static const struct pci_device_id pci_ids[] = { | |||
| 1055 | .driver_data = (kernel_ulong_t)&sdhci_o2, | 931 | .driver_data = (kernel_ulong_t)&sdhci_o2, |
| 1056 | }, | 932 | }, |
| 1057 | 933 | ||
| 934 | { | ||
| 935 | .vendor = PCI_VENDOR_ID_O2, | ||
| 936 | .device = PCI_DEVICE_ID_O2_FUJIN2, | ||
| 937 | .subvendor = PCI_ANY_ID, | ||
| 938 | .subdevice = PCI_ANY_ID, | ||
| 939 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
| 940 | }, | ||
| 941 | |||
| 942 | { | ||
| 943 | .vendor = PCI_VENDOR_ID_O2, | ||
| 944 | .device = PCI_DEVICE_ID_O2_SDS0, | ||
| 945 | .subvendor = PCI_ANY_ID, | ||
| 946 | .subdevice = PCI_ANY_ID, | ||
| 947 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
| 948 | }, | ||
| 949 | |||
| 950 | { | ||
| 951 | .vendor = PCI_VENDOR_ID_O2, | ||
| 952 | .device = PCI_DEVICE_ID_O2_SDS1, | ||
| 953 | .subvendor = PCI_ANY_ID, | ||
| 954 | .subdevice = PCI_ANY_ID, | ||
| 955 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
| 956 | }, | ||
| 957 | |||
| 958 | { | ||
| 959 | .vendor = PCI_VENDOR_ID_O2, | ||
| 960 | .device = PCI_DEVICE_ID_O2_SEABIRD0, | ||
| 961 | .subvendor = PCI_ANY_ID, | ||
| 962 | .subdevice = PCI_ANY_ID, | ||
| 963 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
| 964 | }, | ||
| 965 | |||
| 966 | { | ||
| 967 | .vendor = PCI_VENDOR_ID_O2, | ||
| 968 | .device = PCI_DEVICE_ID_O2_SEABIRD1, | ||
| 969 | .subvendor = PCI_ANY_ID, | ||
| 970 | .subdevice = PCI_ANY_ID, | ||
| 971 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
| 972 | }, | ||
| 973 | |||
| 1058 | { /* Generic SD host controller */ | 974 | { /* Generic SD host controller */ |
| 1059 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) | 975 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) |
| 1060 | }, | 976 | }, |
| @@ -1457,6 +1373,15 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( | |||
| 1457 | 1373 | ||
| 1458 | sdhci_pci_add_own_cd(slot); | 1374 | sdhci_pci_add_own_cd(slot); |
| 1459 | 1375 | ||
| 1376 | /* | ||
| 1377 | * Check if the chip needs a separate GPIO for card detect to wake up | ||
| 1378 | * from runtime suspend. If it is not there, don't allow runtime PM. | ||
| 1379 | * Note sdhci_pci_add_own_cd() sets slot->cd_gpio to -EINVAL on failure. | ||
| 1380 | */ | ||
| 1381 | if (chip->fixes && chip->fixes->own_cd_for_runtime_pm && | ||
| 1382 | !gpio_is_valid(slot->cd_gpio)) | ||
| 1383 | chip->allow_runtime_pm = false; | ||
| 1384 | |||
| 1460 | return slot; | 1385 | return slot; |
| 1461 | 1386 | ||
| 1462 | remove: | 1387 | remove: |
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h new file mode 100644 index 000000000000..6d718719659e --- /dev/null +++ b/drivers/mmc/host/sdhci-pci.h | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | #ifndef __SDHCI_PCI_H | ||
| 2 | #define __SDHCI_PCI_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * PCI device IDs | ||
| 6 | */ | ||
| 7 | |||
| 8 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 | ||
| 9 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a | ||
| 10 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC 0x0f14 | ||
| 11 | #define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 | ||
| 12 | #define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 | ||
| 13 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC2 0x0f50 | ||
| 14 | #define PCI_DEVICE_ID_INTEL_MRFL_MMC 0x1190 | ||
| 15 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO0 0x08f9 | ||
| 16 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO1 0x08fa | ||
| 17 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO2 0x08fb | ||
| 18 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC0 0x08e5 | ||
| 19 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC1 0x08e6 | ||
| 20 | |||
| 21 | /* | ||
| 22 | * PCI registers | ||
| 23 | */ | ||
| 24 | |||
| 25 | #define PCI_SDHCI_IFPIO 0x00 | ||
| 26 | #define PCI_SDHCI_IFDMA 0x01 | ||
| 27 | #define PCI_SDHCI_IFVENDOR 0x02 | ||
| 28 | |||
| 29 | #define PCI_SLOT_INFO 0x40 /* 8 bits */ | ||
| 30 | #define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) | ||
| 31 | #define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 | ||
| 32 | |||
| 33 | #define MAX_SLOTS 8 | ||
| 34 | |||
| 35 | struct sdhci_pci_chip; | ||
| 36 | struct sdhci_pci_slot; | ||
| 37 | |||
| 38 | struct sdhci_pci_fixes { | ||
| 39 | unsigned int quirks; | ||
| 40 | unsigned int quirks2; | ||
| 41 | bool allow_runtime_pm; | ||
| 42 | bool own_cd_for_runtime_pm; | ||
| 43 | |||
| 44 | int (*probe) (struct sdhci_pci_chip *); | ||
| 45 | |||
| 46 | int (*probe_slot) (struct sdhci_pci_slot *); | ||
| 47 | void (*remove_slot) (struct sdhci_pci_slot *, int); | ||
| 48 | |||
| 49 | int (*suspend) (struct sdhci_pci_chip *); | ||
| 50 | int (*resume) (struct sdhci_pci_chip *); | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct sdhci_pci_slot { | ||
| 54 | struct sdhci_pci_chip *chip; | ||
| 55 | struct sdhci_host *host; | ||
| 56 | struct sdhci_pci_data *data; | ||
| 57 | |||
| 58 | int pci_bar; | ||
| 59 | int rst_n_gpio; | ||
| 60 | int cd_gpio; | ||
| 61 | int cd_irq; | ||
| 62 | |||
| 63 | void (*hw_reset)(struct sdhci_host *host); | ||
| 64 | }; | ||
| 65 | |||
| 66 | struct sdhci_pci_chip { | ||
| 67 | struct pci_dev *pdev; | ||
| 68 | |||
| 69 | unsigned int quirks; | ||
| 70 | unsigned int quirks2; | ||
| 71 | bool allow_runtime_pm; | ||
| 72 | const struct sdhci_pci_fixes *fixes; | ||
| 73 | |||
| 74 | int num_slots; /* Slots on controller */ | ||
| 75 | struct sdhci_pci_slot *slots[MAX_SLOTS]; /* Pointers to host slots */ | ||
| 76 | }; | ||
| 77 | |||
| 78 | #endif /* __SDHCI_PCI_H */ | ||
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index e2065a44dffc..bef250e95418 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
| @@ -237,19 +237,21 @@ int sdhci_pltfm_unregister(struct platform_device *pdev) | |||
| 237 | EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister); | 237 | EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister); |
| 238 | 238 | ||
| 239 | #ifdef CONFIG_PM | 239 | #ifdef CONFIG_PM |
| 240 | static int sdhci_pltfm_suspend(struct device *dev) | 240 | int sdhci_pltfm_suspend(struct device *dev) |
| 241 | { | 241 | { |
| 242 | struct sdhci_host *host = dev_get_drvdata(dev); | 242 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 243 | 243 | ||
| 244 | return sdhci_suspend_host(host); | 244 | return sdhci_suspend_host(host); |
| 245 | } | 245 | } |
| 246 | EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend); | ||
| 246 | 247 | ||
| 247 | static int sdhci_pltfm_resume(struct device *dev) | 248 | int sdhci_pltfm_resume(struct device *dev) |
| 248 | { | 249 | { |
| 249 | struct sdhci_host *host = dev_get_drvdata(dev); | 250 | struct sdhci_host *host = dev_get_drvdata(dev); |
| 250 | 251 | ||
| 251 | return sdhci_resume_host(host); | 252 | return sdhci_resume_host(host); |
| 252 | } | 253 | } |
| 254 | EXPORT_SYMBOL_GPL(sdhci_pltfm_resume); | ||
| 253 | 255 | ||
| 254 | const struct dev_pm_ops sdhci_pltfm_pmops = { | 256 | const struct dev_pm_ops sdhci_pltfm_pmops = { |
| 255 | .suspend = sdhci_pltfm_suspend, | 257 | .suspend = sdhci_pltfm_suspend, |
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index e15ced79f7ed..04bc2481e5c3 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h | |||
| @@ -111,6 +111,8 @@ static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host) | |||
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | #ifdef CONFIG_PM | 113 | #ifdef CONFIG_PM |
| 114 | extern int sdhci_pltfm_suspend(struct device *dev); | ||
| 115 | extern int sdhci_pltfm_resume(struct device *dev); | ||
| 114 | extern const struct dev_pm_ops sdhci_pltfm_pmops; | 116 | extern const struct dev_pm_ops sdhci_pltfm_pmops; |
| 115 | #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) | 117 | #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) |
| 116 | #else | 118 | #else |
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 5b7b2eba8a54..a835898a68dd 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
| @@ -198,6 +198,7 @@ static struct sdhci_tegra_soc_data soc_data_tegra114 = { | |||
| 198 | }; | 198 | }; |
| 199 | 199 | ||
| 200 | static const struct of_device_id sdhci_tegra_dt_match[] = { | 200 | static const struct of_device_id sdhci_tegra_dt_match[] = { |
| 201 | { .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra114 }, | ||
| 201 | { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 }, | 202 | { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 }, |
| 202 | { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, | 203 | { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, |
| 203 | { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, | 204 | { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index bd8a0982aec3..9ddef4763541 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -898,8 +898,13 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, | |||
| 898 | u16 mode; | 898 | u16 mode; |
| 899 | struct mmc_data *data = cmd->data; | 899 | struct mmc_data *data = cmd->data; |
| 900 | 900 | ||
| 901 | if (data == NULL) | 901 | if (data == NULL) { |
| 902 | /* clear Auto CMD settings for no data CMDs */ | ||
| 903 | mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); | ||
| 904 | sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | | ||
| 905 | SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE); | ||
| 902 | return; | 906 | return; |
| 907 | } | ||
| 903 | 908 | ||
| 904 | WARN_ON(!host->data); | 909 | WARN_ON(!host->data); |
| 905 | 910 | ||
| @@ -1013,7 +1018,12 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
| 1013 | mdelay(1); | 1018 | mdelay(1); |
| 1014 | } | 1019 | } |
| 1015 | 1020 | ||
| 1016 | mod_timer(&host->timer, jiffies + 10 * HZ); | 1021 | timeout = jiffies; |
| 1022 | if (!cmd->data && cmd->cmd_timeout_ms > 9000) | ||
| 1023 | timeout += DIV_ROUND_UP(cmd->cmd_timeout_ms, 1000) * HZ + HZ; | ||
| 1024 | else | ||
| 1025 | timeout += 10 * HZ; | ||
| 1026 | mod_timer(&host->timer, timeout); | ||
| 1017 | 1027 | ||
| 1018 | host->cmd = cmd; | 1028 | host->cmd = cmd; |
| 1019 | 1029 | ||
| @@ -1391,6 +1401,13 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 1391 | mmc->card->type == MMC_TYPE_MMC ? | 1401 | mmc->card->type == MMC_TYPE_MMC ? |
| 1392 | MMC_SEND_TUNING_BLOCK_HS200 : | 1402 | MMC_SEND_TUNING_BLOCK_HS200 : |
| 1393 | MMC_SEND_TUNING_BLOCK; | 1403 | MMC_SEND_TUNING_BLOCK; |
| 1404 | |||
| 1405 | /* Here we need to set the host->mrq to NULL, | ||
| 1406 | * in case the pending finish_tasklet | ||
| 1407 | * finishes it incorrectly. | ||
| 1408 | */ | ||
| 1409 | host->mrq = NULL; | ||
| 1410 | |||
| 1394 | spin_unlock_irqrestore(&host->lock, flags); | 1411 | spin_unlock_irqrestore(&host->lock, flags); |
| 1395 | sdhci_execute_tuning(mmc, tuning_opcode); | 1412 | sdhci_execute_tuning(mmc, tuning_opcode); |
| 1396 | spin_lock_irqsave(&host->lock, flags); | 1413 | spin_lock_irqsave(&host->lock, flags); |
| @@ -1845,12 +1862,12 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 1845 | unsigned long timeout; | 1862 | unsigned long timeout; |
| 1846 | int err = 0; | 1863 | int err = 0; |
| 1847 | bool requires_tuning_nonuhs = false; | 1864 | bool requires_tuning_nonuhs = false; |
| 1865 | unsigned long flags; | ||
| 1848 | 1866 | ||
| 1849 | host = mmc_priv(mmc); | 1867 | host = mmc_priv(mmc); |
| 1850 | 1868 | ||
| 1851 | sdhci_runtime_pm_get(host); | 1869 | sdhci_runtime_pm_get(host); |
| 1852 | disable_irq(host->irq); | 1870 | spin_lock_irqsave(&host->lock, flags); |
| 1853 | spin_lock(&host->lock); | ||
| 1854 | 1871 | ||
| 1855 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1872 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
| 1856 | 1873 | ||
| @@ -1870,15 +1887,13 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 1870 | requires_tuning_nonuhs) | 1887 | requires_tuning_nonuhs) |
| 1871 | ctrl |= SDHCI_CTRL_EXEC_TUNING; | 1888 | ctrl |= SDHCI_CTRL_EXEC_TUNING; |
| 1872 | else { | 1889 | else { |
| 1873 | spin_unlock(&host->lock); | 1890 | spin_unlock_irqrestore(&host->lock, flags); |
| 1874 | enable_irq(host->irq); | ||
| 1875 | sdhci_runtime_pm_put(host); | 1891 | sdhci_runtime_pm_put(host); |
| 1876 | return 0; | 1892 | return 0; |
| 1877 | } | 1893 | } |
| 1878 | 1894 | ||
| 1879 | if (host->ops->platform_execute_tuning) { | 1895 | if (host->ops->platform_execute_tuning) { |
| 1880 | spin_unlock(&host->lock); | 1896 | spin_unlock_irqrestore(&host->lock, flags); |
| 1881 | enable_irq(host->irq); | ||
| 1882 | err = host->ops->platform_execute_tuning(host, opcode); | 1897 | err = host->ops->platform_execute_tuning(host, opcode); |
| 1883 | sdhci_runtime_pm_put(host); | 1898 | sdhci_runtime_pm_put(host); |
| 1884 | return err; | 1899 | return err; |
| @@ -1951,15 +1966,12 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 1951 | host->cmd = NULL; | 1966 | host->cmd = NULL; |
| 1952 | host->mrq = NULL; | 1967 | host->mrq = NULL; |
| 1953 | 1968 | ||
| 1954 | spin_unlock(&host->lock); | 1969 | spin_unlock_irqrestore(&host->lock, flags); |
| 1955 | enable_irq(host->irq); | ||
| 1956 | |||
| 1957 | /* Wait for Buffer Read Ready interrupt */ | 1970 | /* Wait for Buffer Read Ready interrupt */ |
| 1958 | wait_event_interruptible_timeout(host->buf_ready_int, | 1971 | wait_event_interruptible_timeout(host->buf_ready_int, |
| 1959 | (host->tuning_done == 1), | 1972 | (host->tuning_done == 1), |
| 1960 | msecs_to_jiffies(50)); | 1973 | msecs_to_jiffies(50)); |
| 1961 | disable_irq(host->irq); | 1974 | spin_lock_irqsave(&host->lock, flags); |
| 1962 | spin_lock(&host->lock); | ||
| 1963 | 1975 | ||
| 1964 | if (!host->tuning_done) { | 1976 | if (!host->tuning_done) { |
| 1965 | pr_info(DRIVER_NAME ": Timeout waiting for " | 1977 | pr_info(DRIVER_NAME ": Timeout waiting for " |
| @@ -2034,8 +2046,7 @@ out: | |||
| 2034 | err = 0; | 2046 | err = 0; |
| 2035 | 2047 | ||
| 2036 | sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier); | 2048 | sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier); |
| 2037 | spin_unlock(&host->lock); | 2049 | spin_unlock_irqrestore(&host->lock, flags); |
| 2038 | enable_irq(host->irq); | ||
| 2039 | sdhci_runtime_pm_put(host); | 2050 | sdhci_runtime_pm_put(host); |
| 2040 | 2051 | ||
| 2041 | return err; | 2052 | return err; |
| @@ -3004,7 +3015,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 3004 | /* SD3.0: SDR104 is supported so (for eMMC) the caps2 | 3015 | /* SD3.0: SDR104 is supported so (for eMMC) the caps2 |
| 3005 | * field can be promoted to support HS200. | 3016 | * field can be promoted to support HS200. |
| 3006 | */ | 3017 | */ |
| 3007 | mmc->caps2 |= MMC_CAP2_HS200; | 3018 | if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) |
| 3019 | mmc->caps2 |= MMC_CAP2_HS200; | ||
| 3008 | } else if (caps[1] & SDHCI_SUPPORT_SDR50) | 3020 | } else if (caps[1] & SDHCI_SUPPORT_SDR50) |
| 3009 | mmc->caps |= MMC_CAP_UHS_SDR50; | 3021 | mmc->caps |= MMC_CAP_UHS_SDR50; |
| 3010 | 3022 | ||
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index d032b080ac4d..54730f4aac87 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
| @@ -381,73 +381,75 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host) | |||
| 381 | desc, cookie); | 381 | desc, cookie); |
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | static void sh_mmcif_request_dma(struct sh_mmcif_host *host, | 384 | static struct dma_chan * |
| 385 | struct sh_mmcif_plat_data *pdata) | 385 | sh_mmcif_request_dma_one(struct sh_mmcif_host *host, |
| 386 | struct sh_mmcif_plat_data *pdata, | ||
| 387 | enum dma_transfer_direction direction) | ||
| 386 | { | 388 | { |
| 387 | struct resource *res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); | ||
| 388 | struct dma_slave_config cfg; | 389 | struct dma_slave_config cfg; |
| 390 | struct dma_chan *chan; | ||
| 391 | unsigned int slave_id; | ||
| 392 | struct resource *res; | ||
| 389 | dma_cap_mask_t mask; | 393 | dma_cap_mask_t mask; |
| 390 | int ret; | 394 | int ret; |
| 391 | 395 | ||
| 392 | host->dma_active = false; | ||
| 393 | |||
| 394 | if (pdata) { | ||
| 395 | if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) | ||
| 396 | return; | ||
| 397 | } else if (!host->pd->dev.of_node) { | ||
| 398 | return; | ||
| 399 | } | ||
| 400 | |||
| 401 | /* We can only either use DMA for both Tx and Rx or not use it at all */ | ||
| 402 | dma_cap_zero(mask); | 396 | dma_cap_zero(mask); |
| 403 | dma_cap_set(DMA_SLAVE, mask); | 397 | dma_cap_set(DMA_SLAVE, mask); |
| 404 | 398 | ||
| 405 | host->chan_tx = dma_request_slave_channel_compat(mask, shdma_chan_filter, | 399 | if (pdata) |
| 406 | pdata ? (void *)pdata->slave_id_tx : NULL, | 400 | slave_id = direction == DMA_MEM_TO_DEV |
| 407 | &host->pd->dev, "tx"); | 401 | ? pdata->slave_id_tx : pdata->slave_id_rx; |
| 408 | dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__, | 402 | else |
| 409 | host->chan_tx); | 403 | slave_id = 0; |
| 410 | 404 | ||
| 411 | if (!host->chan_tx) | 405 | chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, |
| 412 | return; | 406 | (void *)(unsigned long)slave_id, &host->pd->dev, |
| 407 | direction == DMA_MEM_TO_DEV ? "tx" : "rx"); | ||
| 408 | |||
| 409 | dev_dbg(&host->pd->dev, "%s: %s: got channel %p\n", __func__, | ||
| 410 | direction == DMA_MEM_TO_DEV ? "TX" : "RX", chan); | ||
| 411 | |||
| 412 | if (!chan) | ||
| 413 | return NULL; | ||
| 414 | |||
| 415 | res = platform_get_resource(host->pd, IORESOURCE_MEM, 0); | ||
| 413 | 416 | ||
| 414 | /* In the OF case the driver will get the slave ID from the DT */ | 417 | /* In the OF case the driver will get the slave ID from the DT */ |
| 415 | if (pdata) | 418 | cfg.slave_id = slave_id; |
| 416 | cfg.slave_id = pdata->slave_id_tx; | 419 | cfg.direction = direction; |
| 417 | cfg.direction = DMA_MEM_TO_DEV; | ||
| 418 | cfg.dst_addr = res->start + MMCIF_CE_DATA; | 420 | cfg.dst_addr = res->start + MMCIF_CE_DATA; |
| 419 | cfg.src_addr = 0; | 421 | cfg.src_addr = 0; |
| 420 | ret = dmaengine_slave_config(host->chan_tx, &cfg); | 422 | ret = dmaengine_slave_config(chan, &cfg); |
| 421 | if (ret < 0) | 423 | if (ret < 0) { |
| 422 | goto ecfgtx; | 424 | dma_release_channel(chan); |
| 425 | return NULL; | ||
| 426 | } | ||
| 423 | 427 | ||
| 424 | host->chan_rx = dma_request_slave_channel_compat(mask, shdma_chan_filter, | 428 | return chan; |
| 425 | pdata ? (void *)pdata->slave_id_rx : NULL, | 429 | } |
| 426 | &host->pd->dev, "rx"); | ||
| 427 | dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__, | ||
| 428 | host->chan_rx); | ||
| 429 | 430 | ||
| 430 | if (!host->chan_rx) | 431 | static void sh_mmcif_request_dma(struct sh_mmcif_host *host, |
| 431 | goto erqrx; | 432 | struct sh_mmcif_plat_data *pdata) |
| 433 | { | ||
| 434 | host->dma_active = false; | ||
| 432 | 435 | ||
| 433 | if (pdata) | 436 | if (pdata) { |
| 434 | cfg.slave_id = pdata->slave_id_rx; | 437 | if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0) |
| 435 | cfg.direction = DMA_DEV_TO_MEM; | 438 | return; |
| 436 | cfg.dst_addr = 0; | 439 | } else if (!host->pd->dev.of_node) { |
| 437 | cfg.src_addr = res->start + MMCIF_CE_DATA; | 440 | return; |
| 438 | ret = dmaengine_slave_config(host->chan_rx, &cfg); | 441 | } |
| 439 | if (ret < 0) | ||
| 440 | goto ecfgrx; | ||
| 441 | 442 | ||
| 442 | return; | 443 | /* We can only either use DMA for both Tx and Rx or not use it at all */ |
| 444 | host->chan_tx = sh_mmcif_request_dma_one(host, pdata, DMA_MEM_TO_DEV); | ||
| 445 | if (!host->chan_tx) | ||
| 446 | return; | ||
| 443 | 447 | ||
| 444 | ecfgrx: | 448 | host->chan_rx = sh_mmcif_request_dma_one(host, pdata, DMA_DEV_TO_MEM); |
| 445 | dma_release_channel(host->chan_rx); | 449 | if (!host->chan_rx) { |
| 446 | host->chan_rx = NULL; | 450 | dma_release_channel(host->chan_tx); |
| 447 | erqrx: | 451 | host->chan_tx = NULL; |
| 448 | ecfgtx: | 452 | } |
| 449 | dma_release_channel(host->chan_tx); | ||
| 450 | host->chan_tx = NULL; | ||
| 451 | } | 453 | } |
| 452 | 454 | ||
| 453 | static void sh_mmcif_release_dma(struct sh_mmcif_host *host) | 455 | static void sh_mmcif_release_dma(struct sh_mmcif_host *host) |
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index f344659dceac..2d6ce257a273 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | 33 | ||
| 34 | #include "tmio_mmc.h" | 34 | #include "tmio_mmc.h" |
| 35 | 35 | ||
| 36 | #define EXT_ACC 0xe4 | ||
| 37 | |||
| 36 | struct sh_mobile_sdhi_of_data { | 38 | struct sh_mobile_sdhi_of_data { |
| 37 | unsigned long tmio_flags; | 39 | unsigned long tmio_flags; |
| 38 | }; | 40 | }; |
| @@ -54,7 +56,7 @@ static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int | |||
| 54 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 56 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 55 | struct tmio_mmc_host *host = mmc_priv(mmc); | 57 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 56 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); | 58 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); |
| 57 | int ret = clk_enable(priv->clk); | 59 | int ret = clk_prepare_enable(priv->clk); |
| 58 | if (ret < 0) | 60 | if (ret < 0) |
| 59 | return ret; | 61 | return ret; |
| 60 | 62 | ||
| @@ -67,7 +69,7 @@ static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev) | |||
| 67 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 69 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 68 | struct tmio_mmc_host *host = mmc_priv(mmc); | 70 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 69 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); | 71 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); |
| 70 | clk_disable(priv->clk); | 72 | clk_disable_unprepare(priv->clk); |
| 71 | } | 73 | } |
| 72 | 74 | ||
| 73 | static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) | 75 | static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host) |
| @@ -133,9 +135,15 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 133 | struct tmio_mmc_data *mmc_data; | 135 | struct tmio_mmc_data *mmc_data; |
| 134 | struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; | 136 | struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; |
| 135 | struct tmio_mmc_host *host; | 137 | struct tmio_mmc_host *host; |
| 138 | struct resource *res; | ||
| 136 | int irq, ret, i = 0; | 139 | int irq, ret, i = 0; |
| 137 | bool multiplexed_isr = true; | 140 | bool multiplexed_isr = true; |
| 138 | struct tmio_mmc_dma *dma_priv; | 141 | struct tmio_mmc_dma *dma_priv; |
| 142 | u16 ver; | ||
| 143 | |||
| 144 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 145 | if (!res) | ||
| 146 | return -EINVAL; | ||
| 139 | 147 | ||
| 140 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_mobile_sdhi), GFP_KERNEL); | 148 | priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_mobile_sdhi), GFP_KERNEL); |
| 141 | if (priv == NULL) { | 149 | if (priv == NULL) { |
| @@ -206,11 +214,22 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 206 | mmc_data->flags |= of_data->tmio_flags; | 214 | mmc_data->flags |= of_data->tmio_flags; |
| 207 | } | 215 | } |
| 208 | 216 | ||
| 217 | /* SD control register space size is 0x100, 0x200 for bus_shift=1 */ | ||
| 218 | mmc_data->bus_shift = resource_size(res) >> 9; | ||
| 219 | |||
| 209 | ret = tmio_mmc_host_probe(&host, pdev, mmc_data); | 220 | ret = tmio_mmc_host_probe(&host, pdev, mmc_data); |
| 210 | if (ret < 0) | 221 | if (ret < 0) |
| 211 | goto eprobe; | 222 | goto eprobe; |
| 212 | 223 | ||
| 213 | /* | 224 | /* |
| 225 | * FIXME: | ||
| 226 | * this Workaround can be more clever method | ||
| 227 | */ | ||
| 228 | ver = sd_ctrl_read16(host, CTL_VERSION); | ||
| 229 | if (ver == 0xCB0D) | ||
| 230 | sd_ctrl_write16(host, EXT_ACC, 1); | ||
| 231 | |||
| 232 | /* | ||
| 214 | * Allow one or more specific (named) ISRs or | 233 | * Allow one or more specific (named) ISRs or |
| 215 | * one or more multiplexed (un-named) ISRs. | 234 | * one or more multiplexed (un-named) ISRs. |
| 216 | */ | 235 | */ |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 8860d4d2bc22..1900abb04236 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
| @@ -62,6 +62,7 @@ static int tmio_mmc_probe(struct platform_device *pdev) | |||
| 62 | const struct mfd_cell *cell = mfd_get_cell(pdev); | 62 | const struct mfd_cell *cell = mfd_get_cell(pdev); |
| 63 | struct tmio_mmc_data *pdata; | 63 | struct tmio_mmc_data *pdata; |
| 64 | struct tmio_mmc_host *host; | 64 | struct tmio_mmc_host *host; |
| 65 | struct resource *res; | ||
| 65 | int ret = -EINVAL, irq; | 66 | int ret = -EINVAL, irq; |
| 66 | 67 | ||
| 67 | if (pdev->num_resources != 2) | 68 | if (pdev->num_resources != 2) |
| @@ -84,6 +85,14 @@ static int tmio_mmc_probe(struct platform_device *pdev) | |||
| 84 | goto out; | 85 | goto out; |
| 85 | } | 86 | } |
| 86 | 87 | ||
| 88 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 89 | if (!res) | ||
| 90 | return -EINVAL; | ||
| 91 | |||
| 92 | /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ | ||
| 93 | pdata->bus_shift = resource_size(res) >> 10; | ||
| 94 | pdata->flags |= TMIO_MMC_HAVE_HIGH_REG; | ||
| 95 | |||
| 87 | ret = tmio_mmc_host_probe(&host, pdev, pdata); | 96 | ret = tmio_mmc_host_probe(&host, pdev, pdata); |
| 88 | if (ret) | 97 | if (ret) |
| 89 | goto cell_disable; | 98 | goto cell_disable; |
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 86fd21e00099..aaa9c7e9e730 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h | |||
| @@ -58,7 +58,6 @@ enum tmio_mmc_power { | |||
| 58 | 58 | ||
| 59 | struct tmio_mmc_host { | 59 | struct tmio_mmc_host { |
| 60 | void __iomem *ctl; | 60 | void __iomem *ctl; |
| 61 | unsigned long bus_shift; | ||
| 62 | struct mmc_command *cmd; | 61 | struct mmc_command *cmd; |
| 63 | struct mmc_request *mrq; | 62 | struct mmc_request *mrq; |
| 64 | struct mmc_data *data; | 63 | struct mmc_data *data; |
| @@ -176,19 +175,19 @@ int tmio_mmc_host_runtime_resume(struct device *dev); | |||
| 176 | 175 | ||
| 177 | static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) | 176 | static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) |
| 178 | { | 177 | { |
| 179 | return readw(host->ctl + (addr << host->bus_shift)); | 178 | return readw(host->ctl + (addr << host->pdata->bus_shift)); |
| 180 | } | 179 | } |
| 181 | 180 | ||
| 182 | static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr, | 181 | static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr, |
| 183 | u16 *buf, int count) | 182 | u16 *buf, int count) |
| 184 | { | 183 | { |
| 185 | readsw(host->ctl + (addr << host->bus_shift), buf, count); | 184 | readsw(host->ctl + (addr << host->pdata->bus_shift), buf, count); |
| 186 | } | 185 | } |
| 187 | 186 | ||
| 188 | static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) | 187 | static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) |
| 189 | { | 188 | { |
| 190 | return readw(host->ctl + (addr << host->bus_shift)) | | 189 | return readw(host->ctl + (addr << host->pdata->bus_shift)) | |
| 191 | readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16; | 190 | readw(host->ctl + ((addr + 2) << host->pdata->bus_shift)) << 16; |
| 192 | } | 191 | } |
| 193 | 192 | ||
| 194 | static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val) | 193 | static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val) |
| @@ -198,19 +197,19 @@ static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val | |||
| 198 | */ | 197 | */ |
| 199 | if (host->pdata->write16_hook && host->pdata->write16_hook(host, addr)) | 198 | if (host->pdata->write16_hook && host->pdata->write16_hook(host, addr)) |
| 200 | return; | 199 | return; |
| 201 | writew(val, host->ctl + (addr << host->bus_shift)); | 200 | writew(val, host->ctl + (addr << host->pdata->bus_shift)); |
| 202 | } | 201 | } |
| 203 | 202 | ||
| 204 | static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, | 203 | static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, |
| 205 | u16 *buf, int count) | 204 | u16 *buf, int count) |
| 206 | { | 205 | { |
| 207 | writesw(host->ctl + (addr << host->bus_shift), buf, count); | 206 | writesw(host->ctl + (addr << host->pdata->bus_shift), buf, count); |
| 208 | } | 207 | } |
| 209 | 208 | ||
| 210 | static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val) | 209 | static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val) |
| 211 | { | 210 | { |
| 212 | writew(val, host->ctl + (addr << host->bus_shift)); | 211 | writew(val, host->ctl + (addr << host->pdata->bus_shift)); |
| 213 | writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); | 212 | writew(val >> 16, host->ctl + ((addr + 2) << host->pdata->bus_shift)); |
| 214 | } | 213 | } |
| 215 | 214 | ||
| 216 | 215 | ||
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index 65edb4a62452..03e7b280cb4c 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c | |||
| @@ -293,7 +293,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat | |||
| 293 | if (pdata->dma->chan_priv_tx) | 293 | if (pdata->dma->chan_priv_tx) |
| 294 | cfg.slave_id = pdata->dma->slave_id_tx; | 294 | cfg.slave_id = pdata->dma->slave_id_tx; |
| 295 | cfg.direction = DMA_MEM_TO_DEV; | 295 | cfg.direction = DMA_MEM_TO_DEV; |
| 296 | cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->bus_shift); | 296 | cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->pdata->bus_shift); |
| 297 | cfg.src_addr = 0; | 297 | cfg.src_addr = 0; |
| 298 | ret = dmaengine_slave_config(host->chan_tx, &cfg); | 298 | ret = dmaengine_slave_config(host->chan_tx, &cfg); |
| 299 | if (ret < 0) | 299 | if (ret < 0) |
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index f3b2d8ca1eca..8d8abf23a611 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
| @@ -161,10 +161,8 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) | |||
| 161 | 161 | ||
| 162 | static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) | 162 | static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) |
| 163 | { | 163 | { |
| 164 | struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); | ||
| 165 | |||
| 166 | /* implicit BUG_ON(!res) */ | 164 | /* implicit BUG_ON(!res) */ |
| 167 | if (resource_size(res) > 0x100) { | 165 | if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) { |
| 168 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000); | 166 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000); |
| 169 | msleep(10); | 167 | msleep(10); |
| 170 | } | 168 | } |
| @@ -176,14 +174,12 @@ static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) | |||
| 176 | 174 | ||
| 177 | static void tmio_mmc_clk_start(struct tmio_mmc_host *host) | 175 | static void tmio_mmc_clk_start(struct tmio_mmc_host *host) |
| 178 | { | 176 | { |
| 179 | struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); | ||
| 180 | |||
| 181 | sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 | | 177 | sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 | |
| 182 | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); | 178 | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); |
| 183 | msleep(10); | 179 | msleep(10); |
| 184 | 180 | ||
| 185 | /* implicit BUG_ON(!res) */ | 181 | /* implicit BUG_ON(!res) */ |
| 186 | if (resource_size(res) > 0x100) { | 182 | if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) { |
| 187 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100); | 183 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100); |
| 188 | msleep(10); | 184 | msleep(10); |
| 189 | } | 185 | } |
| @@ -191,16 +187,14 @@ static void tmio_mmc_clk_start(struct tmio_mmc_host *host) | |||
| 191 | 187 | ||
| 192 | static void tmio_mmc_reset(struct tmio_mmc_host *host) | 188 | static void tmio_mmc_reset(struct tmio_mmc_host *host) |
| 193 | { | 189 | { |
| 194 | struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0); | ||
| 195 | |||
| 196 | /* FIXME - should we set stop clock reg here */ | 190 | /* FIXME - should we set stop clock reg here */ |
| 197 | sd_ctrl_write16(host, CTL_RESET_SD, 0x0000); | 191 | sd_ctrl_write16(host, CTL_RESET_SD, 0x0000); |
| 198 | /* implicit BUG_ON(!res) */ | 192 | /* implicit BUG_ON(!res) */ |
| 199 | if (resource_size(res) > 0x100) | 193 | if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) |
| 200 | sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000); | 194 | sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000); |
| 201 | msleep(10); | 195 | msleep(10); |
| 202 | sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); | 196 | sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); |
| 203 | if (resource_size(res) > 0x100) | 197 | if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) |
| 204 | sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001); | 198 | sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001); |
| 205 | msleep(10); | 199 | msleep(10); |
| 206 | } | 200 | } |
| @@ -944,17 +938,25 @@ static const struct mmc_host_ops tmio_mmc_ops = { | |||
| 944 | .enable_sdio_irq = tmio_mmc_enable_sdio_irq, | 938 | .enable_sdio_irq = tmio_mmc_enable_sdio_irq, |
| 945 | }; | 939 | }; |
| 946 | 940 | ||
| 947 | static void tmio_mmc_init_ocr(struct tmio_mmc_host *host) | 941 | static int tmio_mmc_init_ocr(struct tmio_mmc_host *host) |
| 948 | { | 942 | { |
| 949 | struct tmio_mmc_data *pdata = host->pdata; | 943 | struct tmio_mmc_data *pdata = host->pdata; |
| 950 | struct mmc_host *mmc = host->mmc; | 944 | struct mmc_host *mmc = host->mmc; |
| 951 | 945 | ||
| 952 | mmc_regulator_get_supply(mmc); | 946 | mmc_regulator_get_supply(mmc); |
| 953 | 947 | ||
| 948 | /* use ocr_mask if no regulator */ | ||
| 954 | if (!mmc->ocr_avail) | 949 | if (!mmc->ocr_avail) |
| 955 | mmc->ocr_avail = pdata->ocr_mask ? : MMC_VDD_32_33 | MMC_VDD_33_34; | 950 | mmc->ocr_avail = pdata->ocr_mask; |
| 956 | else if (pdata->ocr_mask) | 951 | |
| 957 | dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n"); | 952 | /* |
| 953 | * try again. | ||
| 954 | * There is possibility that regulator has not been probed | ||
| 955 | */ | ||
| 956 | if (!mmc->ocr_avail) | ||
| 957 | return -EPROBE_DEFER; | ||
| 958 | |||
| 959 | return 0; | ||
| 958 | } | 960 | } |
| 959 | 961 | ||
| 960 | static void tmio_mmc_of_parse(struct platform_device *pdev, | 962 | static void tmio_mmc_of_parse(struct platform_device *pdev, |
| @@ -1005,8 +1007,9 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
| 1005 | _host->set_pwr = pdata->set_pwr; | 1007 | _host->set_pwr = pdata->set_pwr; |
| 1006 | _host->set_clk_div = pdata->set_clk_div; | 1008 | _host->set_clk_div = pdata->set_clk_div; |
| 1007 | 1009 | ||
| 1008 | /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ | 1010 | ret = tmio_mmc_init_ocr(_host); |
| 1009 | _host->bus_shift = resource_size(res_ctl) >> 10; | 1011 | if (ret < 0) |
| 1012 | goto host_free; | ||
| 1010 | 1013 | ||
| 1011 | _host->ctl = ioremap(res_ctl->start, resource_size(res_ctl)); | 1014 | _host->ctl = ioremap(res_ctl->start, resource_size(res_ctl)); |
| 1012 | if (!_host->ctl) { | 1015 | if (!_host->ctl) { |
| @@ -1016,14 +1019,13 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, | |||
| 1016 | 1019 | ||
| 1017 | mmc->ops = &tmio_mmc_ops; | 1020 | mmc->ops = &tmio_mmc_ops; |
| 1018 | mmc->caps |= MMC_CAP_4_BIT_DATA | pdata->capabilities; | 1021 | mmc->caps |= MMC_CAP_4_BIT_DATA | pdata->capabilities; |
| 1019 | mmc->caps2 = pdata->capabilities2; | 1022 | mmc->caps2 |= pdata->capabilities2; |
| 1020 | mmc->max_segs = 32; | 1023 | mmc->max_segs = 32; |
| 1021 | mmc->max_blk_size = 512; | 1024 | mmc->max_blk_size = 512; |
| 1022 | mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) * | 1025 | mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) * |
| 1023 | mmc->max_segs; | 1026 | mmc->max_segs; |
| 1024 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 1027 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
| 1025 | mmc->max_seg_size = mmc->max_req_size; | 1028 | mmc->max_seg_size = mmc->max_req_size; |
| 1026 | tmio_mmc_init_ocr(_host); | ||
| 1027 | 1029 | ||
| 1028 | _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD || | 1030 | _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD || |
| 1029 | mmc->caps & MMC_CAP_NEEDS_POLL || | 1031 | mmc->caps & MMC_CAP_NEEDS_POLL || |
