|
@@ -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,
|
|
|
};
|
|
|
|
|
|
/*****************************************************************************\
|