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

Commit 30cf2803 authored by Adrian Hunter's avatar Adrian Hunter Committed by Ulf Hansson
Browse files

mmc: sdhci-pci: Let suspend/resume callbacks replace default callbacks



The suspend / resume callbacks lack the flexibility to allow a device to
specify a different function entirely. Change them around so that device
functions are called directly and they in turn can call the default
implementations if needed.

Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Tested-by: default avatarLudovic Desroches <ludovic.desroches@microchip.com>
parent b7813f0f
Loading
Loading
Loading
Loading
+99 −71
Original line number Diff line number Diff line
@@ -37,6 +37,88 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host);
static void sdhci_pci_set_bus_width(struct sdhci_host *host, int width);
static void sdhci_pci_hw_reset(struct sdhci_host *host);

#ifdef CONFIG_PM_SLEEP
static int __sdhci_pci_suspend_host(struct sdhci_pci_chip *chip)
{
	int i, ret;

	for (i = 0; i < chip->num_slots; i++) {
		struct sdhci_pci_slot *slot = chip->slots[i];
		struct sdhci_host *host;

		if (!slot)
			continue;

		host = slot->host;

		if (chip->pm_retune && host->tuning_mode != SDHCI_TUNING_MODE_3)
			mmc_retune_needed(host->mmc);

		ret = sdhci_suspend_host(host);
		if (ret)
			goto err_pci_suspend;

		if (host->mmc->pm_flags & MMC_PM_WAKE_SDIO_IRQ)
			sdhci_enable_irq_wakeups(host);
	}

	return 0;

err_pci_suspend:
	while (--i >= 0)
		sdhci_resume_host(chip->slots[i]->host);
	return ret;
}

static int sdhci_pci_init_wakeup(struct sdhci_pci_chip *chip)
{
	mmc_pm_flag_t pm_flags = 0;
	int i;

	for (i = 0; i < chip->num_slots; i++) {
		struct sdhci_pci_slot *slot = chip->slots[i];

		if (slot)
			pm_flags |= slot->host->mmc->pm_flags;
	}

	return device_init_wakeup(&chip->pdev->dev,
				  (pm_flags & MMC_PM_KEEP_POWER) &&
				  (pm_flags & MMC_PM_WAKE_SDIO_IRQ));
}

static int sdhci_pci_suspend_host(struct sdhci_pci_chip *chip)
{
	int ret;

	ret = __sdhci_pci_suspend_host(chip);
	if (ret)
		return ret;

	sdhci_pci_init_wakeup(chip);

	return 0;
}

int sdhci_pci_resume_host(struct sdhci_pci_chip *chip)
{
	struct sdhci_pci_slot *slot;
	int i, ret;

	for (i = 0; i < chip->num_slots; i++) {
		slot = chip->slots[i];
		if (!slot)
			continue;

		ret = sdhci_resume_host(slot->host);
		if (ret)
			return ret;
	}

	return 0;
}
#endif

/*****************************************************************************\
 *                                                                           *
 * Hardware specific quirk handling                                          *
@@ -74,7 +156,7 @@ static int ricoh_mmc_resume(struct sdhci_pci_chip *chip)
	/* Otherwise it becomes confused if card state changed
		during suspend */
	msleep(500);
	return 0;
	return sdhci_pci_resume_host(chip);
}
#endif

@@ -758,7 +840,11 @@ static void jmicron_remove_slot(struct sdhci_pci_slot *slot, int dead)
#ifdef CONFIG_PM_SLEEP
static int jmicron_suspend(struct sdhci_pci_chip *chip)
{
	int i;
	int i, ret;

	ret = __sdhci_pci_suspend_host(chip);
	if (ret)
		return ret;

	if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC ||
	    chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) {
@@ -766,6 +852,8 @@ static int jmicron_suspend(struct sdhci_pci_chip *chip)
			jmicron_enable_mmc(chip->slots[i]->host, 0);
	}

	sdhci_pci_init_wakeup(chip);

	return 0;
}

@@ -785,7 +873,7 @@ static int jmicron_resume(struct sdhci_pci_chip *chip)
		return ret;
	}

	return 0;
	return sdhci_pci_resume_host(chip);
}
#endif

@@ -1678,89 +1766,29 @@ static const struct sdhci_ops sdhci_pci_ops = {
static int sdhci_pci_suspend(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct sdhci_pci_chip *chip;
	struct sdhci_pci_slot *slot;
	struct sdhci_host *host;
	mmc_pm_flag_t slot_pm_flags;
	mmc_pm_flag_t pm_flags = 0;
	int i, ret;
	struct sdhci_pci_chip *chip = pci_get_drvdata(pdev);

	chip = pci_get_drvdata(pdev);
	if (!chip)
		return 0;

	for (i = 0; i < chip->num_slots; i++) {
		slot = chip->slots[i];
		if (!slot)
			continue;

		host = slot->host;

		if (chip->pm_retune && host->tuning_mode != SDHCI_TUNING_MODE_3)
			mmc_retune_needed(host->mmc);

		ret = sdhci_suspend_host(host);

		if (ret)
			goto err_pci_suspend;

		slot_pm_flags = host->mmc->pm_flags;
		if (slot_pm_flags & MMC_PM_WAKE_SDIO_IRQ)
			sdhci_enable_irq_wakeups(host);

		pm_flags |= slot_pm_flags;
	}
	if (chip->fixes && chip->fixes->suspend)
		return chip->fixes->suspend(chip);

	if (chip->fixes && chip->fixes->suspend) {
		ret = chip->fixes->suspend(chip);
		if (ret)
			goto err_pci_suspend;
	}

	if (pm_flags & MMC_PM_KEEP_POWER) {
		if (pm_flags & MMC_PM_WAKE_SDIO_IRQ)
			device_init_wakeup(dev, true);
		else
			device_init_wakeup(dev, false);
	} else
		device_init_wakeup(dev, false);

	return 0;

err_pci_suspend:
	while (--i >= 0)
		sdhci_resume_host(chip->slots[i]->host);
	return ret;
	return sdhci_pci_suspend_host(chip);
}

static int sdhci_pci_resume(struct device *dev)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct sdhci_pci_chip *chip;
	struct sdhci_pci_slot *slot;
	int i, ret;
	struct sdhci_pci_chip *chip = pci_get_drvdata(pdev);

	chip = pci_get_drvdata(pdev);
	if (!chip)
		return 0;

	if (chip->fixes && chip->fixes->resume) {
		ret = chip->fixes->resume(chip);
		if (ret)
			return ret;
	}

	for (i = 0; i < chip->num_slots; i++) {
		slot = chip->slots[i];
		if (!slot)
			continue;

		ret = sdhci_resume_host(slot->host);
		if (ret)
			return ret;
	}
	if (chip->fixes && chip->fixes->resume)
		return chip->fixes->resume(chip);

	return 0;
	return sdhci_pci_resume_host(chip);
}
#endif

+1 −1
Original line number Diff line number Diff line
@@ -388,6 +388,6 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip)
{
	sdhci_pci_o2_probe(chip);
	return 0;
	return sdhci_pci_resume_host(chip);
}
#endif
+4 −0
Original line number Diff line number Diff line
@@ -111,4 +111,8 @@ static inline void *sdhci_pci_priv(struct sdhci_pci_slot *slot)
	return (void *)slot->private;
}

#ifdef CONFIG_PM_SLEEP
int sdhci_pci_resume_host(struct sdhci_pci_chip *chip);
#endif

#endif /* __SDHCI_PCI_H */