summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorAisheng.Dong <b29396@freescale.com>2010-08-03 09:58:47 +0800
committerAlan Tull <r80115@freescale.com>2010-09-25 09:49:52 -0500
commit9ed1c4e9efd34e06a084218de494be1f38cf3781 (patch)
tree0a1607f8bbc96af078fa33a43ca67bd147500e37 /drivers/mmc
parent679ab6b0f79b5e3cbde6db7e78994503dd8e37de (diff)
ENGR00125823-2 esdhc: add a interface to let clock always on
Implement platform independent clock always on function. User would use clk_always_on flag in plat_data to decide whether we should let the clock always on for their some specical use cases. Host driver will not handle platform specific clock always on fucntion any more. However, we will reserve the clock always on function for SDIO cards Signed-off-by: Aisheng.Dong <b29396@freescale.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/mx_sdhci.c38
1 files changed, 19 insertions, 19 deletions
diff --git a/drivers/mmc/host/mx_sdhci.c b/drivers/mmc/host/mx_sdhci.c
index 64529482f63d..76b3e4a0057f 100644
--- a/drivers/mmc/host/mx_sdhci.c
+++ b/drivers/mmc/host/mx_sdhci.c
@@ -813,6 +813,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
host->plat_data->clk_flg = 1;
}
}
+
if (clock == host->clock && !(ios.bus_width & MMC_BUS_WIDTH_DDR))
return;
@@ -852,6 +853,14 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
DBG("prescaler = 0x%x, divider = 0x%x\n", prescaler, div);
clk |= (prescaler << 8) | (div << 4);
+ if (host->plat_data->clk_always_on
+ | (host->mmc->card && mmc_card_sdio(host->mmc->card)))
+ clk |= SDHCI_CLOCK_PER_EN | SDHCI_CLOCK_HLK_EN
+ | SDHCI_CLOCK_IPG_EN;
+ else
+ clk &= ~(SDHCI_CLOCK_PER_EN | SDHCI_CLOCK_HLK_EN
+ | SDHCI_CLOCK_IPG_EN);
+
/* Configure the clock delay line */
if ((host->plat_data->vendor_ver >= ESDHC_VENDOR_V3)
&& host->plat_data->dll_override_en)
@@ -1083,7 +1092,7 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
{
struct sdhci_host *host;
unsigned long flags;
- u32 ier, prot, clk, present;
+ u32 ier, prot, present;
host = mmc_priv(mmc);
@@ -1096,19 +1105,13 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
if (--(host->sdio_enable))
goto exit_unlock;
}
- /* Enable the clock */
- if (!host->plat_data->clk_flg) {
- clk_enable(host->clk);
- host->plat_data->clk_flg = 1;
- }
+
ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE);
prot = readl(host->ioaddr + SDHCI_HOST_CONTROL);
- clk = readl(host->ioaddr + SDHCI_CLOCK_CONTROL);
if (enable) {
ier |= SDHCI_INT_CARD_INT;
prot |= SDHCI_CTRL_D3CD;
- clk |= SDHCI_CLOCK_PER_EN | SDHCI_CLOCK_IPG_EN;
present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
if ((present & SDHCI_CARD_INT_MASK) != SDHCI_CARD_INT_ID)
writel(SDHCI_INT_CARD_INT,
@@ -1116,12 +1119,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
} else {
ier &= ~SDHCI_INT_CARD_INT;
prot &= ~SDHCI_CTRL_D3CD;
- clk &= ~(SDHCI_CLOCK_PER_EN | SDHCI_CLOCK_IPG_EN);
}
writel(prot, host->ioaddr + SDHCI_HOST_CONTROL);
writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE);
- writel(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
mmiowb();
exit_unlock:
@@ -1231,17 +1232,13 @@ static void sdhci_tasklet_finish(unsigned long param)
/* Stop the clock when the req is done */
req_done = !(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
(SDHCI_DATA_ACTIVE | SDHCI_DOING_WRITE | SDHCI_DOING_READ));
- /* Do not disable the eSDHC clk on MX35 3DS board,
- * since SYSTEM can't boot up after the reset key
- * is pressed when the SD/MMC boot mode is used.
- * The root cause is that the ROM code don't ensure
- * the SD/MMC clk is running when boot system.
- * */
- if (!machine_is_mx35_3ds() && req_done && host->plat_data->clk_flg &&
- !(host->mmc && host->mmc->card && mmc_card_sdio(host->mmc->card))) {
+ if (req_done && host->plat_data->clk_flg &&
+ !(host->plat_data->clk_always_on) &&
+ !(host->mmc->card && mmc_card_sdio(host->mmc->card))) {
clk_disable(host->clk);
host->plat_data->clk_flg = 0;
}
+
mmc_request_done(host->mmc, mrq);
}
@@ -1803,8 +1800,11 @@ static int __devinit sdhci_probe_slot(struct platform_device
/* Get the SDHC clock from clock system APIs */
host->clk = clk_get(&pdev->dev, mmc_plat->clock_mmc);
- if (IS_ERR(host->clk))
+ if (NULL == host->clk) {
printk(KERN_ERR "MXC MMC can't get clock.\n");
+ goto out1;
+ } else
+ clk_enable(host->clk);
DBG("SDHC:%d clock:%lu\n", pdev->id, clk_get_rate(host->clk));
host->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);