mmc: msm_sdcc: Added hardware reset functionality for SD cards

In error situations, sometimes the card doesn't respond to commands.
To recover from such situations, a power-cycle is issued to the card
and it is reinitialized.

msmsdcc_hw_reset:	Defined in mmc host operations 'hw_reset'.
			This function power-cycles the card.

CRs-fixed: 375869
Change-Id: I2b02649ae3befe700a7a2401b93eb69c8014a4ce
Signed-off-by: Asutosh Das <asutoshd@codeaurora.org>
This commit is contained in:
Asutosh Das
2012-07-09 19:08:26 +05:30
committed by Stephen Boyd
parent b9100e4b65
commit 3b1258a65e

View File

@@ -2385,8 +2385,10 @@ static int msmsdcc_setup_vreg(struct msmsdcc_host *host, bool enable,
struct msm_mmc_reg_data *vreg_table[2];
curr_slot = host->plat->vreg_data;
if (!curr_slot)
if (!curr_slot) {
rc = -EINVAL;
goto out;
}
vreg_table[0] = curr_slot->vdd_data;
vreg_table[1] = curr_slot->vdd_io_data;
@@ -3988,6 +3990,51 @@ exit:
return rc;
}
/*
* Work around of the unavailability of a power_reset functionality in SD cards
* by turning the OFF & back ON the regulators supplying the SD card.
*/
void msmsdcc_hw_reset(struct mmc_host *mmc)
{
struct mmc_card *card = mmc->card;
struct msmsdcc_host *host = mmc_priv(mmc);
int rc;
/* Write-protection bits would be lost on a hardware reset in emmc */
if (!card || !mmc_card_sd(card))
return;
/*
* Continuing on failing to disable regulator would lead to a panic
* anyway, since the commands would fail and console would be flooded
* with prints, eventually leading to a watchdog bark
*/
rc = msmsdcc_setup_vreg(host, false, false);
if (rc) {
pr_err("%s: %s disable regulator: failed: %d\n",
mmc_hostname(mmc), __func__, rc);
BUG_ON(rc);
}
/* 10ms delay for the supply to reach the desired voltage level */
usleep_range(10000, 12000);
/*
* Continuing on failing to enable regulator would lead to a panic
* anyway, since the commands would fail and console would be flooded
* with prints, eventually leading to a watchdog bark
*/
rc = msmsdcc_setup_vreg(host, true, false);
if (rc) {
pr_err("%s: %s enable regulator: failed: %d\n",
mmc_hostname(mmc), __func__, rc);
BUG_ON(rc);
}
/* 10ms delay for the supply to reach the desired voltage level */
usleep_range(10000, 12000);
}
static const struct mmc_host_ops msmsdcc_ops = {
.enable = msmsdcc_enable,
.disable = msmsdcc_disable,
@@ -3998,7 +4045,8 @@ static const struct mmc_host_ops msmsdcc_ops = {
.get_ro = msmsdcc_get_ro,
.enable_sdio_irq = msmsdcc_enable_sdio_irq,
.start_signal_voltage_switch = msmsdcc_switch_io_voltage,
.execute_tuning = msmsdcc_execute_tuning
.execute_tuning = msmsdcc_execute_tuning,
.hw_reset = msmsdcc_hw_reset,
};
static unsigned int
@@ -5595,7 +5643,7 @@ msmsdcc_probe(struct platform_device *pdev)
mmc->caps |= plat->mmc_bus_width;
mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
mmc->caps |= MMC_CAP_HW_RESET;
/*
* If we send the CMD23 before multi block write/read command
* then we need not to send CMD12 at the end of the transfer.