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

Commit 2f4cbb3d authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Linus Torvalds
Browse files

sdio: sdhci support for suspend mode PM features



Tested with an XO v1.5 from OLPC.

Signed-off-by: default avatarNicolas Pitre <nico@marvell.com>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent da68c4eb
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -501,6 +501,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
{
	struct sdhci_pci_chip *chip;
	struct sdhci_pci_slot *slot;
	mmc_pm_flag_t pm_flags = 0;
	int i, ret;

	chip = pci_get_drvdata(pdev);
@@ -519,6 +520,8 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
				sdhci_resume_host(chip->slots[i]->host);
			return ret;
		}

		pm_flags |= slot->host->mmc->pm_flags;
	}

	if (chip->fixes && chip->fixes->suspend) {
@@ -531,9 +534,15 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
	}

	pci_save_state(pdev);
	if (pm_flags & MMC_PM_KEEP_POWER) {
		if (pm_flags & MMC_PM_WAKE_SDIO_IRQ)
			pci_enable_wake(pdev, PCI_D3hot, 1);
		pci_set_power_state(pdev, PCI_D3hot);
	} else {
		pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
		pci_disable_device(pdev);
		pci_set_power_state(pdev, pci_choose_state(pdev, state));
	}

	return 0;
}
@@ -653,6 +662,8 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
			goto unmap;
	}

	host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;

	ret = sdhci_add_host(host);
	if (ret)
		goto remove;
+17 −9
Original line number Diff line number Diff line
@@ -174,8 +174,13 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
		sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
}

static void sdhci_init(struct sdhci_host *host)
static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);

static void sdhci_init(struct sdhci_host *host, int soft)
{
	if (soft)
		sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
	else
		sdhci_reset(host, SDHCI_RESET_ALL);

	sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
@@ -183,11 +188,17 @@ static void sdhci_init(struct sdhci_host *host)
		SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
		SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
		SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);

	if (soft) {
		/* force clock reconfiguration */
		host->clock = 0;
		sdhci_set_ios(host->mmc, &host->mmc->ios);
	}
}

static void sdhci_reinit(struct sdhci_host *host)
{
	sdhci_init(host);
	sdhci_init(host, 0);
	sdhci_enable_card_detection(host);
}

@@ -1600,16 +1611,13 @@ int sdhci_resume_host(struct sdhci_host *host)
	if (ret)
		return ret;

	sdhci_init(host);
	sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
	mmiowb();

	ret = mmc_resume_host(host->mmc);
	if (ret)
		return ret;

	sdhci_enable_card_detection(host);

	return 0;
	return ret;
}

EXPORT_SYMBOL_GPL(sdhci_resume_host);
@@ -1864,7 +1872,7 @@ int sdhci_add_host(struct sdhci_host *host)
	if (ret)
		goto untasklet;

	sdhci_init(host);
	sdhci_init(host, 0);

#ifdef CONFIG_MMC_DEBUG
	sdhci_dumpregs(host);