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

Commit ae628903 authored by Pierre Ossman's avatar Pierre Ossman
Browse files

sdhci: avoid changing voltage needlessly



Because of granularity issues, sometimes we told the hardware to change
to the voltage we were already at. Rework the logic so this doesn't
happen.

Signed-off-by: default avatarPierre Ossman <pierre@ossman.eu>
parent 7ceeb6a4
Loading
Loading
Loading
Loading
+28 −25
Original line number Diff line number Diff line
@@ -1005,50 +1005,53 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
{
	u8 pwr;

	if (host->power == power)
		return;

	if (power == (unsigned short)-1) {
		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
		goto out;
	}

	/*
	 * Spec says that we should clear the power reg before setting
	 * a new value. Some controllers don't seem to like this though.
	 */
	if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);

	pwr = SDHCI_POWER_ON;

	if (power == (unsigned short)-1)
		pwr = 0;
	else {
		switch (1 << power) {
		case MMC_VDD_165_195:
		pwr |= SDHCI_POWER_180;
			pwr = SDHCI_POWER_180;
			break;
		case MMC_VDD_29_30:
		case MMC_VDD_30_31:
		pwr |= SDHCI_POWER_300;
			pwr = SDHCI_POWER_300;
			break;
		case MMC_VDD_32_33:
		case MMC_VDD_33_34:
		pwr |= SDHCI_POWER_330;
			pwr = SDHCI_POWER_330;
			break;
		default:
			BUG();
		}
	}

	if (host->pwr == pwr)
		return;

	host->pwr = pwr;

	if (pwr == 0) {
		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
		return;
	}

	/*
	 * Spec says that we should clear the power reg before setting
	 * a new value. Some controllers don't seem to like this though.
	 */
	if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);

	/*
	 * At least the Marvell CaFe chip gets confused if we set the voltage
	 * and set turn on power at the same time, so set the voltage first.
	 */
	if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER))
		sdhci_writeb(host, pwr & ~SDHCI_POWER_ON, SDHCI_POWER_CONTROL);

		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);

out:
	host->power = power;
	pwr |= SDHCI_POWER_ON;

	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
}

/*****************************************************************************\
+1 −1
Original line number Diff line number Diff line
@@ -255,7 +255,7 @@ struct sdhci_host {
	unsigned int		timeout_clk;	/* Timeout freq (KHz) */

	unsigned int		clock;		/* Current clock (MHz) */
	unsigned short		power;		/* Current voltage */
	u8			pwr;		/* Current voltage */

	struct mmc_request	*mrq;		/* Current request */
	struct mmc_command	*cmd;		/* Current command */