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

Commit 63d235dc authored by Sahitya Tummala's avatar Sahitya Tummala Committed by Xiaonian Wang
Browse files

mmc: sdhci: Add check_power_status host operation



MSM SDHCI doesn't control power as specified by the Standard
Host Controller 3.0 spec. Writing to power control register/
reset register/voltage bit of host control register would
trigger an IRQ with appropriate status bits set. Hence, use
host op check_power_status after writing to power control
register to check the status and wait until the IRQ is handled.

Change-Id: Ied1a82e385547f7f5d60807fc896ea5a13084657
Signed-off-by: default avatarSahitya Tummala <stummala@codeaurora.org>
[venkatg@codeaurora.org: fix trivial merge conflicts]
Signed-off-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
[subhashj@codeaurora.org: fixed minor merge conflict
& compilation error]
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
[xiaonian@codeaurora.org: fix trivial merge conflict]
Signed-off-by: default avatarXiaonian Wang <xiaonian@codeaurora.org>
parent 494003b1
Loading
Loading
Loading
Loading
+22 −6
Original line number Diff line number Diff line
@@ -198,6 +198,10 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)
	/* Wait max 100 ms */
	timeout = 100;

	if (host->ops->check_power_status && host->pwr &&
	    (mask & SDHCI_RESET_ALL))
		host->ops->check_power_status(host);

	/* hw clears the bit when it's done */
	while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
		if (timeout == 0) {
@@ -1463,6 +1467,8 @@ void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,

	if (pwr == 0) {
		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
		if (host->ops->check_power_status)
			host->ops->check_power_status(host);
		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
			sdhci_runtime_pm_bus_off(host);
	} else {
@@ -1470,20 +1476,27 @@ void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
		 * 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))
		if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) {
			sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);

			if (host->ops->check_power_status)
				host->ops->check_power_status(host);
		}
		/*
		 * 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)
		if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) {
			sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
			if (host->ops->check_power_status)
				host->ops->check_power_status(host);
		}

		pwr |= SDHCI_POWER_ON;

		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
		if (host->ops->check_power_status)
			host->ops->check_power_status(host);

		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
			sdhci_runtime_pm_bus_on(host);
@@ -1650,10 +1663,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
	unsigned long flags;
	u8 ctrl;

	spin_lock_irqsave(&host->lock, flags);

	if (host->flags & SDHCI_DEVICE_DEAD) {
		spin_unlock_irqrestore(&host->lock, flags);
		if (!IS_ERR(mmc->supply.vmmc) &&
		    ios->power_mode == MMC_POWER_OFF)
			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
@@ -1692,6 +1702,8 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
		if (ios->power_mode & (MMC_POWER_UP | MMC_POWER_ON))
			sdhci_set_power(host, ios->power_mode, ios->vdd);

	spin_lock_irqsave(&host->lock, flags);

	if (host->ops->platform_send_init_74_clocks)
		host->ops->platform_send_init_74_clocks(host, ios->power_mode);

@@ -1943,6 +1955,8 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
		/* Set 1.8V Signal Enable in the Host Control2 register to 0 */
		ctrl &= ~SDHCI_CTRL_VDD_180;
		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
		if (host->ops->check_power_status)
			host->ops->check_power_status(host);

		if (!IS_ERR(mmc->supply.vqmmc)) {
			ret = mmc_regulator_set_vqmmc(mmc, ios);
@@ -1982,6 +1996,8 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
		 */
		ctrl |= SDHCI_CTRL_VDD_180;
		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
		if (host->ops->check_power_status)
			host->ops->check_power_status(host);

		/* Some controller need to do more when switching */
		if (host->ops->voltage_switch)