diff options
author | Samsung OSRC <osrc@samsung.com> | 2013-01-08 23:54:22 +0100 |
---|---|---|
committer | Andrew Dodd <atd7@cornell.edu> | 2013-01-08 21:59:46 -0500 |
commit | da8461692362317a8ffce4d4646953985fcf4e1d (patch) | |
tree | ee2cd8c091f04768bb9d12c019ac9917194d0857 /drivers/mmc/core/mmc.c | |
parent | 126b49a7dfaf964d4c82e8b2a70524ef1de27cba (diff) | |
download | kernel_samsung_smdk4412-da8461692362317a8ffce4d4646953985fcf4e1d.zip kernel_samsung_smdk4412-da8461692362317a8ffce4d4646953985fcf4e1d.tar.gz kernel_samsung_smdk4412-da8461692362317a8ffce4d4646953985fcf4e1d.tar.bz2 |
mmc: Soft-patch MoviNAND VTU00M (16GB) eMMC failure
Signed-off-by: Andrei F <luxneb@gmail.com>
Diffstat (limited to 'drivers/mmc/core/mmc.c')
-rw-r--r-- | drivers/mmc/core/mmc.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 81a77a8..3403f53 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -16,6 +16,7 @@ #include <linux/mmc/host.h> #include <linux/mmc/card.h> #include <linux/mmc/mmc.h> +#include <linux/string.h> #include "core.h" #include "bus.h" @@ -107,6 +108,7 @@ static int mmc_decode_cid(struct mmc_card *card) card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); + card->cid.prod_rev = UNSTUFF_BITS(resp, 48, 8); card->cid.serial = UNSTUFF_BITS(resp, 16, 32); card->cid.month = UNSTUFF_BITS(resp, 12, 4); card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; @@ -1492,6 +1494,15 @@ static int mmc_resume(struct mmc_host *host) mmc_claim_host(host); err = mmc_init_card(host, host->ocr, host->card); + + if (host->card->movi_ops == 0x2) { + err = mmc_start_movi_operation(host->card); + if (err) { + pr_warning("%s: movi operation is failed\n", + mmc_hostname(host)); + } + } + mmc_release_host(host); return err; @@ -1504,6 +1515,15 @@ static int mmc_power_restore(struct mmc_host *host) host->card->state &= ~MMC_STATE_HIGHSPEED; mmc_claim_host(host); ret = mmc_init_card(host, host->ocr, host->card); + + if (host->card->movi_ops == 0x2) { + ret = mmc_start_movi_operation(host->card); + if (ret) { + pr_warning("%s: movi operation is failed\n", + mmc_hostname(host)); + } + } + mmc_release_host(host); return ret; @@ -1634,6 +1654,20 @@ int mmc_attach_mmc(struct mmc_host *host) if (err) goto remove_card; + if (!strncmp(host->card->cid.prod_name, "VTU00M", 6) && + (host->card->cid.prod_rev == 0xf1) && + (mmc_start_movi_smart(host->card) == 0x2)) + host->card->movi_ops = 0x2; + + if (host->card->movi_ops == 0x2) { + err = mmc_start_movi_operation(host->card); + if (err) { + pr_warning("%s: movi operation is failed\n", + mmc_hostname(host)); + goto remove_card; + } + } + return 0; remove_card: |