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: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Ludovic Desroches <ludovic.desroches@microchip.com>
This commit is contained in:
Adrian Hunter 2017-03-20 19:50:51 +02:00 committed by Ulf Hansson
parent b7813f0fe9
commit 30cf2803b2
3 changed files with 104 additions and 72 deletions

View File

@ -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_set_bus_width(struct sdhci_host *host, int width);
static void sdhci_pci_hw_reset(struct sdhci_host *host); 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 * * 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 /* Otherwise it becomes confused if card state changed
during suspend */ during suspend */
msleep(500); msleep(500);
return 0; return sdhci_pci_resume_host(chip);
} }
#endif #endif
@ -758,7 +840,11 @@ static void jmicron_remove_slot(struct sdhci_pci_slot *slot, int dead)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int jmicron_suspend(struct sdhci_pci_chip *chip) 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 || if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC ||
chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) { 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); jmicron_enable_mmc(chip->slots[i]->host, 0);
} }
sdhci_pci_init_wakeup(chip);
return 0; return 0;
} }
@ -785,7 +873,7 @@ static int jmicron_resume(struct sdhci_pci_chip *chip)
return ret; return ret;
} }
return 0; return sdhci_pci_resume_host(chip);
} }
#endif #endif
@ -1678,89 +1766,29 @@ static const struct sdhci_ops sdhci_pci_ops = {
static int sdhci_pci_suspend(struct device *dev) static int sdhci_pci_suspend(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct sdhci_pci_chip *chip; struct sdhci_pci_chip *chip = pci_get_drvdata(pdev);
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;
chip = pci_get_drvdata(pdev);
if (!chip) if (!chip)
return 0; return 0;
for (i = 0; i < chip->num_slots; i++) { if (chip->fixes && chip->fixes->suspend)
slot = chip->slots[i]; return chip->fixes->suspend(chip);
if (!slot)
continue;
host = slot->host; return sdhci_pci_suspend_host(chip);
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) {
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;
} }
static int sdhci_pci_resume(struct device *dev) static int sdhci_pci_resume(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct sdhci_pci_chip *chip; struct sdhci_pci_chip *chip = pci_get_drvdata(pdev);
struct sdhci_pci_slot *slot;
int i, ret;
chip = pci_get_drvdata(pdev);
if (!chip) if (!chip)
return 0; return 0;
if (chip->fixes && chip->fixes->resume) { if (chip->fixes && chip->fixes->resume)
ret = chip->fixes->resume(chip); return chip->fixes->resume(chip);
if (ret)
return ret;
}
for (i = 0; i < chip->num_slots; i++) { return sdhci_pci_resume_host(chip);
slot = chip->slots[i];
if (!slot)
continue;
ret = sdhci_resume_host(slot->host);
if (ret)
return ret;
}
return 0;
} }
#endif #endif

View File

@ -388,6 +388,6 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip) int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip)
{ {
sdhci_pci_o2_probe(chip); sdhci_pci_o2_probe(chip);
return 0; return sdhci_pci_resume_host(chip);
} }
#endif #endif

View File

@ -111,4 +111,8 @@ static inline void *sdhci_pci_priv(struct sdhci_pci_slot *slot)
return (void *)slot->private; return (void *)slot->private;
} }
#ifdef CONFIG_PM_SLEEP
int sdhci_pci_resume_host(struct sdhci_pci_chip *chip);
#endif
#endif /* __SDHCI_PCI_H */ #endif /* __SDHCI_PCI_H */