Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9291d531 authored by Krishna Konda's avatar Krishna Konda Committed by Stephen Boyd
Browse files

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: default avatarKrishna Konda <kkonda@codeaurora.org>
parent 35fe2f97
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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;
};

/*
+2 −1
Original line number Diff line number Diff line
@@ -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 */
+28 −11
Original line number Diff line number Diff line
@@ -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) {
	} 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",