aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/Kconfig11
-rw-r--r--drivers/mmc/host/mshci-s3c.c18
-rw-r--r--drivers/mmc/host/mshci.c8
-rw-r--r--drivers/mmc/host/sdhci-s3c.c51
-rw-r--r--drivers/mmc/host/sdhci.c35
-rw-r--r--drivers/mmc/host/sdhci.h1
6 files changed, 80 insertions, 44 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index e231dcc..d6a7e81 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -54,6 +54,17 @@ config MMC_MSHCI_ASYNC_OPS
If unsure, say N.
+config MMC_MSHCI_ENABLE_CACHE
+ tristate "Use Cache defined in eMMC 4.5"
+ depends on MMC_MSHCI
+ default n
+ help
+ This selects eMMC cache control feature of eMMC4.5.
+ These functions might make the performance of MMC better.
+ This should be used when the eMMC device supports cache feature.
+
+ If unsure, say N.
+
config MMC_SDHCI
tristate "Secure Digital Host Controller Interface support"
depends on HAS_DMA
diff --git a/drivers/mmc/host/mshci-s3c.c b/drivers/mmc/host/mshci-s3c.c
index 5023d10..58670ca 100644
--- a/drivers/mmc/host/mshci-s3c.c
+++ b/drivers/mmc/host/mshci-s3c.c
@@ -408,13 +408,14 @@ static int __devinit mshci_s3c_probe(struct platform_device *pdev)
if (parent_clk) {
#ifdef CONFIG_EXYNOS4_MSHC_EPLL_45MHZ
if (!strcmp("fout_epll", \
- parent_clk->name)) {
- clk_set_rate \
+ parent_clk->name) &&
+ soc_is_exynos4210()) {
+ clk_set_rate \
(parent_clk, 180633600);
pdata->cfg_ddr(pdev, 0);
#elif defined(CONFIG_EXYNOS4_MSHC_VPLL_46MHZ)
if (!strcmp("fout_vpll", \
- parent_clk->name)) {
+ parent_clk->name)) {
clk_set_rate \
(parent_clk, 370882812);
pdata->cfg_ddr(pdev, 0);
@@ -460,7 +461,7 @@ static int __devinit mshci_s3c_probe(struct platform_device *pdev)
if (!host->ioaddr) {
dev_err(dev, "failed to map registers\n");
ret = -ENXIO;
- goto err_req_regs;
+ goto err_add_host;
}
/* Ensure we have minimal gpio selected CMD/CLK/Detect */
@@ -541,8 +542,9 @@ static int __devinit mshci_s3c_probe(struct platform_device *pdev)
return 0;
err_add_host:
- release_resource(sc->ioarea);
- kfree(sc->ioarea);
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ release_mem_region(sc->ioarea->start, resource_size(sc->ioarea));
err_req_regs:
for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
@@ -629,7 +631,11 @@ static void __exit mshci_s3c_exit(void)
platform_driver_unregister(&mshci_s3c_driver);
}
+#ifdef CONFIG_FAST_RESUME
+beforeresume_initcall(mshci_s3c_init);
+#else
module_init(mshci_s3c_init);
+#endif
module_exit(mshci_s3c_exit);
MODULE_DESCRIPTION("Samsung MSHCI (HSMMC) glue");
diff --git a/drivers/mmc/host/mshci.c b/drivers/mmc/host/mshci.c
index 9431405..45997c5 100644
--- a/drivers/mmc/host/mshci.c
+++ b/drivers/mmc/host/mshci.c
@@ -1134,7 +1134,7 @@ static void mshci_request(struct mmc_host *mmc, struct mmc_request *mrq)
/* We shouldn't wait for data inihibit for stop commands, even
though they might use busy signaling */
- if (mrq->cmd->opcode == 12) {
+ if ((mrq->cmd->opcode == 12) || (mrq->cmd->opcode == 13)) {
/* nothing to do */
} else {
for (;;) {
@@ -1619,7 +1619,8 @@ static void mshci_cmd_irq(struct mshci_host *host, u32 intmask)
/* to notify an error happend */
host->error_state = 1;
#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_P4NOTE) || \
- defined(CONFIG_MACH_C1_USA_ATT)
+ defined(CONFIG_MACH_C1_USA_ATT) \
+ || defined(CONFIG_MACH_GRANDE) || defined(CONFIG_MACH_IRON)
if (host->mmc && host->mmc->card)
mshci_dumpregs(host);
#endif
@@ -1704,7 +1705,8 @@ static void mshci_data_irq(struct mshci_host *host, u32 intmask, u8 intr_src)
/* to notify an error happend */
host->error_state = 1;
#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_P4NOTE) || \
- defined(CONFIG_MACH_C1_USA_ATT)
+ defined(CONFIG_MACH_C1_USA_ATT) \
+ || defined(CONFIG_MACH_GRANDE) || defined(CONFIG_MACH_IRON)
if (host->mmc && host->mmc->card)
mshci_dumpregs(host);
#endif
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 5a81b34..97b40b8 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -386,17 +386,11 @@ static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
pr_info("%s: card inserted.\n",
mmc_hostname(host->mmc));
host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
-#ifdef CONFIG_MACH_MIDAS_01_BD
- sdhci_s3c_vtf_on_off(1);
-#endif
} else {
dev_dbg(&dev->dev, "card removed.\n");
pr_info("%s: card removed.\n",
mmc_hostname(host->mmc));
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
-#ifdef CONFIG_MACH_MIDAS_01_BD
- sdhci_s3c_vtf_on_off(0);
-#endif
}
tasklet_schedule(&host->card_tasklet);
spin_unlock_irqrestore(&host->lock, flags);
@@ -586,7 +580,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
if (!host->ioaddr) {
dev_err(dev, "failed to map registers\n");
ret = -ENXIO;
- goto err_req_regs;
+ goto err_add_host;
}
/* Ensure we have minimal gpio selected CMD/CLK/Detect */
@@ -652,11 +646,6 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
if (pdata->pm_flags)
host->mmc->pm_flags |= pdata->pm_flags;
-#ifdef CONFIG_MACH_MIDAS_01_BD
- /* before calling shhci_add_host, you should turn vdd_tflash on */
- sdhci_s3c_vtf_on_off(1);
-#endif
-
/* To turn on vmmc regulator only if sd card exists,
GPIO pin for card detection should be initialized.
Moved from sdhci_s3c_setup_card_detect_gpio() function */
@@ -721,20 +710,12 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
gpio_is_valid(pdata->ext_cd_gpio))
sdhci_s3c_setup_card_detect_gpio(sc);
-#ifdef CONFIG_MACH_MIDAS_01_BD
- /* if card dose not exist, it should turn vtf off */
- if (pdata->cd_type == S3C_SDHCI_CD_GPIO &&
- sdhci_s3c_get_card_exist(host))
- sdhci_s3c_vtf_on_off(1);
- else
- sdhci_s3c_vtf_on_off(0);
-#endif
-
return 0;
err_add_host:
- release_resource(sc->ioarea);
- kfree(sc->ioarea);
+ if (host->ioaddr)
+ iounmap(host->ioaddr);
+ release_mem_region(sc->ioarea->start, resource_size(sc->ioarea));
err_req_regs:
for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
@@ -798,26 +779,21 @@ static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
ret = sdhci_suspend_host(host, pm);
-#ifdef CONFIG_MACH_MIDAS_01_BD
- /* turn vdd_tflash off */
- sdhci_s3c_vtf_on_off(0);
-#endif
return ret;
}
+static void sdhci_s3c_shutdown(struct platform_device *dev)
+{
+ struct sdhci_host *host = platform_get_drvdata(dev);
+
+ sdhci_shutdown_host(host);
+}
+
static int sdhci_s3c_resume(struct platform_device *dev)
{
struct sdhci_host *host = platform_get_drvdata(dev);
int ret = 0;
-#ifdef CONFIG_MACH_MIDAS_01_BD
- /* turn vdd_tflash off if a card exists*/
- if (sdhci_s3c_get_card_exist(host))
- sdhci_s3c_vtf_on_off(1);
- else
- sdhci_s3c_vtf_on_off(0);
-
-#endif
ret = sdhci_resume_host(host);
return ret;
}
@@ -832,6 +808,7 @@ static struct platform_driver sdhci_s3c_driver = {
.remove = __devexit_p(sdhci_s3c_remove),
.suspend = sdhci_s3c_suspend,
.resume = sdhci_s3c_resume,
+ .shutdown = sdhci_s3c_shutdown,
.driver = {
.owner = THIS_MODULE,
.name = "s3c-sdhci",
@@ -848,7 +825,11 @@ static void __exit sdhci_s3c_exit(void)
platform_driver_unregister(&sdhci_s3c_driver);
}
+#ifdef CONFIG_FAST_RESUME
+beforeresume_initcall(sdhci_s3c_init);
+#else
module_init(sdhci_s3c_init);
+#endif
module_exit(sdhci_s3c_exit);
MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue");
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 1fe77ad..349f073 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -36,10 +36,12 @@
#define DBG(f, x...) \
pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x)
+#ifndef CONFIG_FAST_RESUME
#if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \
defined(CONFIG_MMC_SDHCI_MODULE))
#define SDHCI_USE_LEDS_CLASS
#endif
+#endif
#define MAX_TUNING_LOOP 40
@@ -1966,6 +1968,10 @@ static void sdhci_tasklet_finish(unsigned long param)
controllers do not like that. */
sdhci_reset(host, SDHCI_RESET_CMD);
sdhci_reset(host, SDHCI_RESET_DATA);
+#ifdef CONFIG_MACH_PX
+ printk(KERN_DEBUG "%s: Controller is resetted!\n",
+ mmc_hostname(host->mmc));
+#endif
}
host->mrq = NULL;
@@ -2062,6 +2068,10 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
if (host->cmd->error) {
tasklet_schedule(&host->finish_tasklet);
+#ifdef CONFIG_MACH_PX
+ printk(KERN_DEBUG "%s: finish tasklet schedule\n",
+ mmc_hostname(host->mmc));
+#endif
return;
}
@@ -2346,6 +2356,28 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
EXPORT_SYMBOL_GPL(sdhci_suspend_host);
+void sdhci_shutdown_host(struct sdhci_host *host)
+{
+ sdhci_disable_card_detection(host);
+
+ free_irq(host->irq, host);
+
+ if (host->vmmc) {
+ if (regulator_is_enabled(host->vmmc)) {
+#ifdef CONFIG_MIDAS_COMMON
+ if (host->ops->set_power)
+ host->ops->set_power(0);
+#endif
+ regulator_disable(host->vmmc);
+ pr_info("%s : MMC Card OFF\n", __func__);
+#if defined(CONFIG_TARGET_LOCALE_KOR)
+ mdelay(5);
+#endif
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(sdhci_shutdown_host);
+
int sdhci_resume_host(struct sdhci_host *host)
{
int ret;
@@ -2660,6 +2692,9 @@ int sdhci_add_host(struct sdhci_host *host)
if (caps[1] & SDHCI_DRIVER_TYPE_D)
mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
+ if (mmc->pm_flags & MMC_PM_IGNORE_SUSPEND_RESUME)
+ mmc->pm_caps |= MMC_PM_KEEP_POWER;
+
/*
* If Power Off Notify capability is enabled by the host,
* set notify to short power off notify timeout value.
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index b04e361..b5f48f8 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -375,6 +375,7 @@ extern int sdhci_add_host(struct sdhci_host *host);
extern void sdhci_remove_host(struct sdhci_host *host, int dead);
#ifdef CONFIG_PM
+extern void sdhci_shutdown_host(struct sdhci_host *host);
extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state);
extern int sdhci_resume_host(struct sdhci_host *host);
extern void sdhci_enable_irq_wakeups(struct sdhci_host *host);