diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/sd.c | 11 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 32 |
2 files changed, 43 insertions, 0 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index fc65475a26ee..b461b290ce25 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -925,6 +925,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, | |||
925 | 925 | ||
926 | /* Card is an ultra-high-speed card */ | 926 | /* Card is an ultra-high-speed card */ |
927 | mmc_sd_card_set_uhs(card); | 927 | mmc_sd_card_set_uhs(card); |
928 | |||
929 | /* | ||
930 | * Since initialization is now complete, enable preset | ||
931 | * value registers for UHS-I cards. | ||
932 | */ | ||
933 | if (host->ops->enable_preset_value) | ||
934 | host->ops->enable_preset_value(host, true); | ||
928 | } else { | 935 | } else { |
929 | /* | 936 | /* |
930 | * Attempt to change to high-speed (if supported) | 937 | * Attempt to change to high-speed (if supported) |
@@ -1095,6 +1102,10 @@ int mmc_attach_sd(struct mmc_host *host) | |||
1095 | if (err) | 1102 | if (err) |
1096 | return err; | 1103 | return err; |
1097 | 1104 | ||
1105 | /* Disable preset value enable if already set since last time */ | ||
1106 | if (host->ops->enable_preset_value) | ||
1107 | host->ops->enable_preset_value(host, false); | ||
1108 | |||
1098 | err = mmc_send_app_op_cond(host, 0, &ocr); | 1109 | err = mmc_send_app_op_cond(host, 0, &ocr); |
1099 | if (err) | 1110 | if (err) |
1100 | return err; | 1111 | return err; |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 8a56eacea34d..a1ab22415883 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -1649,6 +1649,37 @@ out: | |||
1649 | return err; | 1649 | return err; |
1650 | } | 1650 | } |
1651 | 1651 | ||
1652 | static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable) | ||
1653 | { | ||
1654 | struct sdhci_host *host; | ||
1655 | u16 ctrl; | ||
1656 | unsigned long flags; | ||
1657 | |||
1658 | host = mmc_priv(mmc); | ||
1659 | |||
1660 | /* Host Controller v3.00 defines preset value registers */ | ||
1661 | if (host->version < SDHCI_SPEC_300) | ||
1662 | return; | ||
1663 | |||
1664 | spin_lock_irqsave(&host->lock, flags); | ||
1665 | |||
1666 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
1667 | |||
1668 | /* | ||
1669 | * We only enable or disable Preset Value if they are not already | ||
1670 | * enabled or disabled respectively. Otherwise, we bail out. | ||
1671 | */ | ||
1672 | if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { | ||
1673 | ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; | ||
1674 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
1675 | } else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { | ||
1676 | ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; | ||
1677 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
1678 | } | ||
1679 | |||
1680 | spin_unlock_irqrestore(&host->lock, flags); | ||
1681 | } | ||
1682 | |||
1652 | static const struct mmc_host_ops sdhci_ops = { | 1683 | static const struct mmc_host_ops sdhci_ops = { |
1653 | .request = sdhci_request, | 1684 | .request = sdhci_request, |
1654 | .set_ios = sdhci_set_ios, | 1685 | .set_ios = sdhci_set_ios, |
@@ -1656,6 +1687,7 @@ static const struct mmc_host_ops sdhci_ops = { | |||
1656 | .enable_sdio_irq = sdhci_enable_sdio_irq, | 1687 | .enable_sdio_irq = sdhci_enable_sdio_irq, |
1657 | .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, | 1688 | .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, |
1658 | .execute_tuning = sdhci_execute_tuning, | 1689 | .execute_tuning = sdhci_execute_tuning, |
1690 | .enable_preset_value = sdhci_enable_preset_value, | ||
1659 | }; | 1691 | }; |
1660 | 1692 | ||
1661 | /*****************************************************************************\ | 1693 | /*****************************************************************************\ |