diff options
author | Sujit Reddy Thumma | 2012-12-04 05:36:19 -0600 |
---|---|---|
committer | Misael Lopez Cruz | 2015-03-03 13:58:41 -0600 |
commit | 689ff2aa9ad89b36f246d0b0126b608bfdde4039 (patch) | |
tree | e13d76336c5562af027894bc0cb046222e65a646 | |
parent | 14ff337db40c0752a3e83c12cb64ffc7b389654f (diff) | |
download | kernel-audio-689ff2aa9ad89b36f246d0b0126b608bfdde4039.tar.gz kernel-audio-689ff2aa9ad89b36f246d0b0126b608bfdde4039.tar.xz kernel-audio-689ff2aa9ad89b36f246d0b0126b608bfdde4039.zip |
mmc: sdio: Fix SDIO 3.0 UHS-I initialization sequence
According to UHS-I initialization sequence for SDIO 3.0 cards,
the host must set bit[24] (S18R) of OCR register during OCR
handshake to know whether the SDIO card is capable of doing
1.8V I/O.
Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Reviewed-by: Johan Rudholm <johan.rudholm@stericsson.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r-- | drivers/mmc/core/sdio.c | 22 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 8 |
2 files changed, 19 insertions, 11 deletions
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 55a49d066dbd..c7b7b923c433 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -162,10 +162,7 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr) | |||
162 | if (ret) | 162 | if (ret) |
163 | goto out; | 163 | goto out; |
164 | 164 | ||
165 | if (card->host->caps & | 165 | if (mmc_host_uhs(card->host)) { |
166 | (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | | ||
167 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | | ||
168 | MMC_CAP_UHS_DDR50)) { | ||
169 | if (data & SDIO_UHS_DDR50) | 166 | if (data & SDIO_UHS_DDR50) |
170 | card->sw_caps.sd3_bus_mode | 167 | card->sw_caps.sd3_bus_mode |
171 | |= SD_MODE_UHS_DDR50; | 168 | |= SD_MODE_UHS_DDR50; |
@@ -483,8 +480,7 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card) | |||
483 | * If the host doesn't support any of the UHS-I modes, fallback on | 480 | * If the host doesn't support any of the UHS-I modes, fallback on |
484 | * default speed. | 481 | * default speed. |
485 | */ | 482 | */ |
486 | if (!(card->host->caps & (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | | 483 | if (!mmc_host_uhs(card->host)) |
487 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))) | ||
488 | return 0; | 484 | return 0; |
489 | 485 | ||
490 | bus_speed = SDIO_SPEED_SDR12; | 486 | bus_speed = SDIO_SPEED_SDR12; |
@@ -650,11 +646,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
650 | * systems that claim 1.8v signalling in fact do not support | 646 | * systems that claim 1.8v signalling in fact do not support |
651 | * it. | 647 | * it. |
652 | */ | 648 | */ |
653 | if ((ocr & R4_18V_PRESENT) && | 649 | if ((ocr & R4_18V_PRESENT) && mmc_host_uhs(host)) { |
654 | (host->caps & | ||
655 | (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | | ||
656 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | | ||
657 | MMC_CAP_UHS_DDR50))) { | ||
658 | err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, | 650 | err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, |
659 | true); | 651 | true); |
660 | if (err) { | 652 | if (err) { |
@@ -1041,6 +1033,10 @@ static int mmc_sdio_power_restore(struct mmc_host *host) | |||
1041 | goto out; | 1033 | goto out; |
1042 | } | 1034 | } |
1043 | 1035 | ||
1036 | if (mmc_host_uhs(host)) | ||
1037 | /* to query card if 1.8V signalling is supported */ | ||
1038 | host->ocr |= R4_18V_PRESENT; | ||
1039 | |||
1044 | ret = mmc_sdio_init_card(host, host->ocr, host->card, | 1040 | ret = mmc_sdio_init_card(host, host->ocr, host->card, |
1045 | mmc_card_keep_power(host)); | 1041 | mmc_card_keep_power(host)); |
1046 | if (!ret && host->sdio_irqs) | 1042 | if (!ret && host->sdio_irqs) |
@@ -1106,6 +1102,10 @@ int mmc_attach_sdio(struct mmc_host *host) | |||
1106 | /* | 1102 | /* |
1107 | * Detect and init the card. | 1103 | * Detect and init the card. |
1108 | */ | 1104 | */ |
1105 | if (mmc_host_uhs(host)) | ||
1106 | /* to query card if 1.8V signalling is supported */ | ||
1107 | host->ocr |= R4_18V_PRESENT; | ||
1108 | |||
1109 | err = mmc_sdio_init_card(host, host->ocr, NULL, 0); | 1109 | err = mmc_sdio_init_card(host, host->ocr, NULL, 0); |
1110 | if (err) { | 1110 | if (err) { |
1111 | if (err == -EAGAIN) { | 1111 | if (err == -EAGAIN) { |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 6830b56dce09..7c5be5810a84 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -470,6 +470,14 @@ static inline int mmc_boot_partition_access(struct mmc_host *host) | |||
470 | return !(host->caps2 & MMC_CAP2_BOOTPART_NOACC); | 470 | return !(host->caps2 & MMC_CAP2_BOOTPART_NOACC); |
471 | } | 471 | } |
472 | 472 | ||
473 | static inline int mmc_host_uhs(struct mmc_host *host) | ||
474 | { | ||
475 | return host->caps & | ||
476 | (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | | ||
477 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | | ||
478 | MMC_CAP_UHS_DDR50); | ||
479 | } | ||
480 | |||
473 | #ifdef CONFIG_MMC_CLKGATE | 481 | #ifdef CONFIG_MMC_CLKGATE |
474 | void mmc_host_clk_hold(struct mmc_host *host); | 482 | void mmc_host_clk_hold(struct mmc_host *host); |
475 | void mmc_host_clk_release(struct mmc_host *host); | 483 | void mmc_host_clk_release(struct mmc_host *host); |