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:
parent
b7813f0fe9
commit
30cf2803b2
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue