mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
mmc: msm_sdcc: reset sd card at boot time
As per sd spec, if a sd card initialized in UHS mode needs to be reinitialized, then the card should be powered off and then powered on before proceeding with initialization again. Otherwise the sd card reports it does not support UHS mode and can't be initialized as an UHS card. Currently sd card could be left powered on either because its regulator is marked as always on or because the sd card was not run-time suspended at the time of reboot. As a result on reboot, the sd card is not detected as an UHS card. In order to prevent this the sd card is powered off and then powered on at boot time. CRs-fixed: 369644 Change-Id: Ic44fa005a1ac2d59d174b320e5e80dd5323876c3 Signed-off-by: Krishna Konda <kkonda@codeaurora.org>
This commit is contained in:
parent
c395e1b293
commit
dc7422cd01
3 changed files with 39 additions and 12 deletions
|
@ -51,6 +51,15 @@ struct msm_mmc_reg_data {
|
|||
bool always_on;
|
||||
/* is low power mode setting required for this regulator? */
|
||||
bool lpm_sup;
|
||||
/*
|
||||
* Use to indicate if the regulator should be reset at boot time.
|
||||
* Its needed only when sd card's vdd regulator is always on
|
||||
* since always on regulators dont get reset at boot time.
|
||||
*
|
||||
* It is needed for sd 3.0 card to be detected as a sd 3.0 card
|
||||
* on device reboot.
|
||||
*/
|
||||
bool reset_at_init;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -66,7 +66,8 @@ static struct msm_mmc_reg_data mmc_vdd_reg_data[MAX_SDCC_CONTROLLER] = {
|
|||
.lpm_sup = 1,
|
||||
.hpm_uA = 800000, /* 800mA */
|
||||
.lpm_uA = 9000,
|
||||
}
|
||||
.reset_at_init = true,
|
||||
},
|
||||
};
|
||||
|
||||
/* All SDCC controllers may require voting for VDD PAD voltage */
|
||||
|
|
|
@ -2203,7 +2203,7 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int msmsdcc_vreg_disable(struct msm_mmc_reg_data *vreg)
|
||||
static int msmsdcc_vreg_disable(struct msm_mmc_reg_data *vreg, bool is_init)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
|
@ -2225,17 +2225,33 @@ static int msmsdcc_vreg_disable(struct msm_mmc_reg_data *vreg)
|
|||
rc = msmsdcc_vreg_set_voltage(vreg, 0, vreg->high_vol_level);
|
||||
if (rc)
|
||||
goto out;
|
||||
} else if (vreg->is_enabled && vreg->always_on && vreg->lpm_sup) {
|
||||
/* Put always_on regulator in LPM (low power mode) */
|
||||
rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->lpm_uA);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
} else if (vreg->is_enabled && vreg->always_on) {
|
||||
if (!is_init && vreg->lpm_sup) {
|
||||
/* Put always_on regulator in LPM (low power mode) */
|
||||
rc = msmsdcc_vreg_set_optimum_mode(vreg, vreg->lpm_uA);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
} else if (is_init && vreg->reset_at_init) {
|
||||
/**
|
||||
* The regulator might not actually be disabled if it
|
||||
* is shared and in use by other drivers.
|
||||
*/
|
||||
rc = regulator_disable(vreg->reg);
|
||||
if (rc) {
|
||||
pr_err("%s: regulator_disable(%s) failed at " \
|
||||
"bootup. rc=%d\n", __func__,
|
||||
vreg->name, rc);
|
||||
goto out;
|
||||
}
|
||||
vreg->is_enabled = false;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msmsdcc_setup_vreg(struct msmsdcc_host *host, bool enable)
|
||||
static int msmsdcc_setup_vreg(struct msmsdcc_host *host, bool enable,
|
||||
bool is_init)
|
||||
{
|
||||
int rc = 0, i;
|
||||
struct msm_mmc_slot_reg_data *curr_slot;
|
||||
|
@ -2253,7 +2269,8 @@ static int msmsdcc_setup_vreg(struct msmsdcc_host *host, bool enable)
|
|||
if (enable)
|
||||
rc = msmsdcc_vreg_enable(vreg_table[i]);
|
||||
else
|
||||
rc = msmsdcc_vreg_disable(vreg_table[i]);
|
||||
rc = msmsdcc_vreg_disable(vreg_table[i],
|
||||
is_init);
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
@ -2270,10 +2287,10 @@ static int msmsdcc_vreg_reset(struct msmsdcc_host *host)
|
|||
{
|
||||
int rc;
|
||||
|
||||
rc = msmsdcc_setup_vreg(host, 1);
|
||||
rc = msmsdcc_setup_vreg(host, 1, true);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = msmsdcc_setup_vreg(host, 0);
|
||||
rc = msmsdcc_setup_vreg(host, 0, true);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -2566,7 +2583,7 @@ static u32 msmsdcc_setup_pwr(struct msmsdcc_host *host, struct mmc_ios *ios)
|
|||
if (host->plat->translate_vdd && !host->sdio_gpio_lpm)
|
||||
ret = host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
|
||||
else if (!host->plat->translate_vdd && !host->sdio_gpio_lpm)
|
||||
ret = msmsdcc_setup_vreg(host, !!ios->vdd);
|
||||
ret = msmsdcc_setup_vreg(host, !!ios->vdd, false);
|
||||
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to setup voltage regulators\n",
|
||||
|
|
Loading…
Reference in a new issue