@@ -949,6 +949,12 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
}
}
+ /*
+ * Since initialization is now complete, enable preset
+ * value registers.
+ */
+ host->ops->enable_preset_value(host);
+
host->card = card;
return 0;
@@ -1614,6 +1614,40 @@ out:
spin_unlock_irqrestore(&host->lock, flags);
}
+static void sdhci_enable_preset_value(struct mmc_host *mmc)
+{
+ 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);
+ ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
+ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void sdhci_disable_preset_value(struct sdhci_host *host)
+{
+ u16 ctrl;
+
+ /* Only for Host Controller version >= v3.00 */
+ if (host->version < SDHCI_SPEC_300)
+ return;
+
+ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
+ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+}
+
static const struct mmc_host_ops sdhci_ops = {
.request = sdhci_request,
.set_ios = sdhci_set_ios,
@@ -1622,6 +1656,7 @@ static const struct mmc_host_ops sdhci_ops = {
.start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
.get_max_current_180 = sdhci_get_max_current_180,
.execute_tuning = sdhci_execute_tuning,
+ .enable_preset_value = sdhci_enable_preset_value,
};
/*****************************************************************************\
@@ -1932,6 +1967,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
tasklet_schedule(&host->card_tasklet);
+ sdhci_disable_preset_value(host);
}
intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
@@ -130,6 +130,7 @@ struct mmc_host_ops {
int (*start_signal_voltage_switch)(struct mmc_host *host);
int (*get_max_current_180)(struct mmc_host *mmc);
void (*execute_tuning)(struct mmc_host *host);
+ void (*enable_preset_value)(struct mmc_host *host);
};
struct mmc_card;