summaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/sd.c11
-rw-r--r--drivers/mmc/host/sdhci.c32
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,
/* Card is an ultra-high-speed card */
mmc_sd_card_set_uhs(card);
+
+ /*
+ * Since initialization is now complete, enable preset
+ * value registers for UHS-I cards.
+ */
+ if (host->ops->enable_preset_value)
+ host->ops->enable_preset_value(host, true);
} else {
/*
* Attempt to change to high-speed (if supported)
@@ -1095,6 +1102,10 @@ int mmc_attach_sd(struct mmc_host *host)
if (err)
return err;
+ /* Disable preset value enable if already set since last time */
+ if (host->ops->enable_preset_value)
+ host->ops->enable_preset_value(host, false);
+
err = mmc_send_app_op_cond(host, 0, &ocr);
if (err)
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:
return err;
}
+static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
+{
+ struct sdhci_host *host;
+ u16 ctrl;
+ unsigned long flags;
+
+ host = mmc_priv(mmc);
+
+ /* Host Controller v3.00 defines preset value registers */
+ if (host->version < SDHCI_SPEC_300)
+ return;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+ /*
+ * We only enable or disable Preset Value if they are not already
+ * enabled or disabled respectively. Otherwise, we bail out.
+ */
+ if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
+ ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
+ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+ } else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
+ ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
+ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+ }
+
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
static const struct mmc_host_ops sdhci_ops = {
.request = sdhci_request,
.set_ios = sdhci_set_ios,
@@ -1656,6 +1687,7 @@ static const struct mmc_host_ops sdhci_ops = {
.enable_sdio_irq = sdhci_enable_sdio_irq,
.start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
.execute_tuning = sdhci_execute_tuning,
+ .enable_preset_value = sdhci_enable_preset_value,
};
/*****************************************************************************\