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

Commit abe24b0a authored by Bao D. Nguyen's avatar Bao D. Nguyen
Browse files

mmc: sdhci-msm: Fix issue with 1.8v switch sequence



This is a porting of the logic of the commit <dc18298fc>.
The SD3.0 voltage switch sequence to 1.8v would involve stopping the
SDCLK before changing the voltage level and with recent changes in 3.10
kernel, the peripheral clocks are also getting disabled instead of
just stopping the clock to the card. This patch makes sure this doesn't
happen by marking the flag card_clock_off in struct mmc_host before
starting the voltage switch sequence and checking it in host controller
driver.

Change-Id: Ic20661b5e3c4d5cd88a2b2132901f306928df4bf
Signed-off-by: default avatarBao D. Nguyen <nguyenb@codeaurora.org>
parent cc7a8b2d
Loading
Loading
Loading
Loading
+8 −21
Original line number Diff line number Diff line
@@ -2573,18 +2573,23 @@ int mmc_host_set_uhs_voltage(struct mmc_host *host)
	 * During a signal voltage level switch, the clock must be gated
	 * for 5 ms according to the SD spec
	 */
	host->card_clock_off = true;
	clock = host->ios.clock;
	host->ios.clock = 0;
	mmc_set_ios(host);

	if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180))
	if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) {
		host->ios.clock = clock;
		mmc_set_ios(host);
		host->card_clock_off = false;
		return -EAGAIN;
	}

	/* Keep clock gated for at least 10 ms, though spec only says 5 ms */
	mmc_delay(10);
	host->ios.clock = clock;
	mmc_set_ios(host);

	host->card_clock_off = false;
	return 0;
}

@@ -2592,7 +2597,6 @@ int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr)
{
	struct mmc_command cmd = {};
	int err = 0;
	u32 clock;

	/*
	 * If we cannot switch voltages, return failure so the caller
@@ -2630,33 +2634,16 @@ int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr)
		err = -EAGAIN;
		goto power_cycle;
	}
	/*
	 * During a signal voltage level switch, the clock must be gated
	 * for 5 ms according to the SD spec
	 */
	host->card_clock_off = true;
	clock = host->ios.clock;
	host->ios.clock = 0;
	mmc_set_ios(host);

	if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) {
	if (mmc_host_set_uhs_voltage(host)) {
		/*
		 * Voltages may not have been switched, but we've already
		 * sent CMD11, so a power cycle is required anyway
		 */
		err = -EAGAIN;
		host->ios.clock = clock;
		mmc_set_ios(host);
		host->card_clock_off = false;
		goto power_cycle;
	}

	/* Keep clock gated for at least 10 ms, though spec only says 5 ms */
	mmc_delay(10);
	host->ios.clock = clock;
	mmc_set_ios(host);

	host->card_clock_off = false;
	/* Wait for at least 1 ms according to spec */
	mmc_delay(1);