host->ios.power_mode = MMC_POWER_UP;
host->ios.bus_width = MMC_BUS_WIDTH_1;
host->ios.timing = MMC_TIMING_LEGACY;
+ if (host->caps2 & MMC_CAP2_SINGLE_POWERON)
+ host->ios.clock = host->f_init;
+
mmc_set_ios(host);
/* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */
*/
mmc_delay(10);
+ if (host->caps2 & MMC_CAP2_SINGLE_POWERON) {
+ host->ios.power_mode = MMC_POWER_ON;
+ goto skip_power_on;
+ }
+
host->ios.clock = host->f_init;
host->ios.power_mode = MMC_POWER_ON;
*/
mmc_delay(10);
+skip_power_on:
mmc_host_clk_release(host);
}
static void tegra_sdhci_get_clock_freq_for_mode(struct sdhci_host *sdhci,
unsigned int *clock)
{
- struct platform_device *pdev = to_platform_device(mmc_dev(sdhci->mmc));
- const struct tegra_sdhci_platform_data *plat = pdev->dev.platform_data;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
+ struct sdhci_tegra *tegra_host = pltfm_host->priv;
+ const struct tegra_sdhci_platform_data *plat = tegra_host->plat;
unsigned int ios_timing = sdhci->mmc->ios.timing;
unsigned int index;
- if (!(plat->is_fix_clock_freq) || !(pdev->dev.of_node)
- || (ios_timing >= MMC_TIMINGS_MAX_MODES))
+ if (!(plat->is_fix_clock_freq) || (ios_timing >= MMC_TIMINGS_MAX_MODES))
return;
/*
/* disable access to boot partitions */
host->mmc->caps2 |= MMC_CAP2_BOOTPART_NOACC;
host->mmc->caps2 |= MMC_CAP2_PACKED_CMD;
+ host->mmc->caps2 |= MMC_CAP2_SINGLE_POWERON;
if (soc_data->nvquirks & NVQUIRK_EN_STROBE_SUPPORT)
host->mmc->caps2 |= MMC_CAP2_EN_STROBE;
if (plat->pwr_off_during_lp0)
void sdhci_reset(struct sdhci_host *host, u8 mask)
{
- u32 ctrl;
+ u16 ctrl;
unsigned long timeout;
sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
* need to re-configure them after each full reset
*/
if ((mask & SDHCI_RESET_ALL) && host->version >= SDHCI_SPEC_400) {
- ctrl = sdhci_readl(host, SDHCI_ACMD12_ERR);
+ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
ctrl |= SDHCI_HOST_VERSION_4_EN;
if (host->quirks2 & SDHCI_QUIRK2_SUPPORT_64BIT_DMA)
ctrl |= SDHCI_ADDRESSING_64BIT_EN;
- sdhci_writel(host, ctrl, SDHCI_ACMD12_ERR);
+ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
}
}
EXPORT_SYMBOL_GPL(sdhci_reset);
}
timeout = jiffies;
- if (!cmd->data && cmd->busy_timeout > 9000)
- timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ;
- else if ((cmd->opcode == MMC_SWITCH) && (((cmd->arg >> 16) &
+ if ((cmd->opcode == MMC_SWITCH) && (((cmd->arg >> 16) &
EXT_CSD_SANITIZE_START) == EXT_CSD_SANITIZE_START))
timeout += 100 * HZ;
+ else if (!cmd->data && cmd->busy_timeout > 9000)
+ timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ;
else
timeout += 10 * HZ;
+
mod_timer(&host->timer, timeout);
host->cmd = cmd;
!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
sdhci_enable_preset_value(host, false);
- if (!ios->clock || ios->clock != host->clock) {
+ if (ios->clock && ios->clock != host->clock) {
+ spin_unlock_irqrestore(&host->lock, flags);
host->ops->set_clock(host, ios->clock);
host->clock = ios->clock;
+ spin_lock_irqsave(&host->lock, flags);
if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK &&
host->clock) {
}
/* Re-enable SD Clock */
- host->ops->set_clock(host, host->clock);
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ clk |= SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
} else
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
mmiowb();
spin_unlock_irqrestore(&host->lock, flags);
+
+ if (!ios->clock && ios->clock != host->clock) {
+ host->ops->set_clock(host, ios->clock);
+ host->clock = ios->clock;
+ }
}
static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
#define MMC_CAP2_HS533 (1 << 19) /* can support HS533*/
#define MMC_CAP2_CQ (1 << 20) /* can support CQ*/
#define MMC_CAP2_NO_SLEEP_CMD (1 << 21) /* cannot support sleep mode */
+#define MMC_CAP2_SINGLE_POWERON (1 << 22) /* Host can power up in single step */
+
mmc_pm_flag_t pm_caps; /* supported pm features */
#ifdef CONFIG_MMC_CLKGATE
return card->host->ios.timing == MMC_TIMING_MMC_HS400;
}
+static inline bool mmc_card_hs533(struct mmc_card *card)
+{
+ return ((card->host->ios.timing == MMC_TIMING_MMC_HS400) &&
+ (card->host->caps2 & MMC_CAP2_HS533));
+}
+
#endif /* LINUX_MMC_HOST_H */