diff options
author | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 09:48:20 +0200 |
---|---|---|
committer | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 14:02:16 +0200 |
commit | 2489007e7d740ccbc3e0a202914e243ad5178787 (patch) | |
tree | b8e6380ea7b1da63474ad68a5dba997e01146043 /drivers/mmc | |
parent | 5f67568eb31e3a813c7c52461dcf66ade15fc2e7 (diff) | |
download | kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.zip kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.gz kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.bz2 |
merge opensource jb u5
Change-Id: I1aaec157aa196f3448eff8636134fce89a814cf2
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/block.c | 42 | ||||
-rw-r--r-- | drivers/mmc/card/queue.c | 14 | ||||
-rw-r--r-- | drivers/mmc/card/queue.h | 18 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 7 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 16 | ||||
-rw-r--r-- | drivers/mmc/core/sdio.c | 1 | ||||
-rw-r--r--[-rwxr-xr-x] | drivers/mmc/core/sdio_io.c | 0 | ||||
-rw-r--r-- | drivers/mmc/host/Kconfig | 11 | ||||
-rw-r--r-- | drivers/mmc/host/mshci-s3c.c | 18 | ||||
-rw-r--r-- | drivers/mmc/host/mshci.c | 8 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-s3c.c | 51 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 35 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 1 |
13 files changed, 171 insertions, 51 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index a47f1ea..7406c4b 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1015,7 +1015,8 @@ static int mmc_blk_err_check(struct mmc_card *card, if (brq->sbc.error || brq->cmd.error || brq->stop.error || brq->data.error) { #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 (mmc_card_mmc(card)) { pr_err("brq->sbc.opcode=%d," "brq->cmd.opcode=%d.\n", @@ -1354,6 +1355,11 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req) } while (reqs < max_packed_rw - 1) { + /* We should stop no-more packing its nopacked_period */ + if ((card->host->caps2 & MMC_CAP2_ADAPT_PACKED) + && mmc_is_nopacked_period(mq)) + break; + spin_lock_irq(q->queue_lock); next = blk_fetch_request(q); spin_unlock_irq(q->queue_lock); @@ -1939,7 +1945,8 @@ snd_packed_rd: } } #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) /* * It's for Engineering DEBUGGING only * This has to be removed before PVR(guessing) @@ -2016,7 +2023,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) /* complete ongoing async transfer before issuing discard */ if (card->host->areq) mmc_blk_issue_rw_rq(mq, NULL); - if (req->cmd_flags & REQ_SECURE) + if (req->cmd_flags & REQ_SECURE && + !(card->quirks & MMC_QUIRK_MOVINAND_SECURE)) ret = mmc_blk_issue_secdiscard_rq(mq, req); else ret = mmc_blk_issue_discard_rq(mq, req); @@ -2289,6 +2297,8 @@ static int mmc_add_disk(struct mmc_blk_data *md) return ret; } +#define CID_MANFID_SAMSUNG 0x15 + static const struct mmc_fixup blk_fixups[] = { MMC_FIXUP("SEM02G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), @@ -2311,6 +2321,28 @@ static const struct mmc_fixup blk_fixups[] = MMC_QUIRK_BLK_NO_CMD23), MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_BLK_NO_CMD23), + + /* + * Some issue about secure erase/secure trim for Samsung MoviNAND + */ + + MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_MOVINAND_SECURE), + MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_MOVINAND_SECURE), + MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_MOVINAND_SECURE), + MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_MOVINAND_SECURE), + MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_MOVINAND_SECURE), + MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_MOVINAND_SECURE), + MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_MOVINAND_SECURE), + MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_MOVINAND_SECURE), + END_FIXUP }; @@ -2458,7 +2490,11 @@ static void __exit mmc_blk_exit(void) unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); } +#ifdef CONFIG_FAST_RESUME +beforeresume_initcall(mmc_blk_init); +#else module_init(mmc_blk_init); +#endif module_exit(mmc_blk_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index bf5d183..b384995 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -62,6 +62,9 @@ static int mmc_queue_thread(void *d) spin_lock_irq(q->queue_lock); set_current_state(TASK_INTERRUPTIBLE); req = blk_fetch_request(q); + /* set nopacked_period if next request is RT class */ + if (req && IS_RT_CLASS_REQ(req)) + mmc_set_nopacked_period(mq, HZ); mq->mqrq_cur->req = req; spin_unlock_irq(q->queue_lock); @@ -100,6 +103,7 @@ static void mmc_request(struct request_queue *q) { struct mmc_queue *mq = q->queuedata; struct request *req; + struct io_context *ioc; if (!mq) { while ((req = blk_fetch_request(q)) != NULL) { @@ -109,6 +113,14 @@ static void mmc_request(struct request_queue *q) return; } + ioc = get_io_context(GFP_NOWAIT, 0); + if (ioc) { + /* Set nopacked period if requesting process is RT class */ + if (IOPRIO_PRIO_CLASS(ioc->ioprio) == IOPRIO_CLASS_RT) + mmc_set_nopacked_period(mq, HZ); + put_io_context(ioc); + } + if (!mq->mqrq_cur->req && !mq->mqrq_prev->req) wake_up_process(mq->thread); } @@ -182,6 +194,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, mq->mqrq_cur = mqrq_cur; mq->mqrq_prev = mqrq_prev; mq->queue->queuedata = mq; + mq->nopacked_period = 0; + blk_queue_prep_rq(mq->queue, mmc_prep_request); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index be58b3c..f1ba6df 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h @@ -46,6 +46,8 @@ struct mmc_queue { struct mmc_queue_req mqrq[2]; struct mmc_queue_req *mqrq_cur; struct mmc_queue_req *mqrq_prev; + /* Jiffies until which disable packed command. */ + unsigned long nopacked_period; }; extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *, @@ -59,4 +61,20 @@ extern unsigned int mmc_queue_map_sg(struct mmc_queue *, extern void mmc_queue_bounce_pre(struct mmc_queue_req *); extern void mmc_queue_bounce_post(struct mmc_queue_req *); +#define IS_RT_CLASS_REQ(x) \ + (IOPRIO_PRIO_CLASS(req_get_ioprio(x)) == IOPRIO_CLASS_RT) + +static inline void mmc_set_nopacked_period(struct mmc_queue *mq, + unsigned long nopacked_jiffies) +{ + mq->nopacked_period = jiffies + nopacked_jiffies; + smp_wmb(); +} + +static inline int mmc_is_nopacked_period(struct mmc_queue *mq) +{ + smp_rmb(); + return (int)time_is_after_jiffies(mq->nopacked_period); +} + #endif diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index e33a805..ddd6d50 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -214,7 +214,8 @@ static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq) } #if (defined(CONFIG_MIDAS_COMMON) && !defined(CONFIG_EXYNOS4_DEV_DWMCI)) || \ - defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_SLP_NAPLES) + defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_SLP_NAPLES) || \ + defined(CONFIG_MACH_TRATS) #ifndef CONFIG_MMC_POLLING_WAIT_CMD23 if(mrq->sbc) { @@ -2695,7 +2696,11 @@ static void __exit mmc_exit(void) destroy_workqueue(workqueue); } +#ifdef CONFIG_FAST_RESUME +beforeresume_initcall(mmc_init); +#else subsys_initcall(mmc_init); +#endif module_exit(mmc_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 53f0e21..81a77a8 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -118,6 +118,10 @@ static int mmc_decode_cid(struct mmc_card *card) return -EINVAL; } + pr_info("%s: %s: %08x%08x%08x%08x\n", mmc_hostname(card->host), + card->cid.prod_name, + card->raw_cid[0], card->raw_cid[1], + card->raw_cid[2], card->raw_cid[3]); return 0; } @@ -350,7 +354,11 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) } card->ext_csd.rev = ext_csd[EXT_CSD_REV]; - if (card->ext_csd.rev > 6) { + /* eMMC 4.5 : ext_csd rev. is 6 + * eMMC 5.0 : ext_csd rev. is 7 + * It's temporary change. + */ + if (card->ext_csd.rev > 7) { printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", mmc_hostname(card->host), card->ext_csd.rev); err = -EINVAL; @@ -571,8 +579,10 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) } if (card->ext_csd.rev >= 5) { - /* enable discard feature if emmc is 4.41 */ - card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; + /* enable discard feature if emmc is 4.41+ */ + if ((ext_csd[EXT_CSD_VENDOR_SPECIFIC_FIELD + 0] & 0x1) && + (card->cid.manfid == 0x15)) + card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; /* check whether the eMMC card supports HPI */ if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) { diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 979cf0b..620a4b2 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -1058,6 +1058,7 @@ static const struct mmc_bus_ops mmc_sdio_ops = { .alive = mmc_sdio_alive, }; + /* * Starting point for SDIO card init. */ diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c index 3169452..3169452 100755..100644 --- a/drivers/mmc/core/sdio_io.c +++ b/drivers/mmc/core/sdio_io.c 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); |