diff options
| author | Nicolas Pitre <nico@fluxnic.net> | 2010-03-05 16:43:32 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-06 14:26:37 -0500 |
| commit | 2f4cbb3d834922ffa0309b6a08fa42dac87ef9d2 (patch) | |
| tree | 9c4b919b3851d3e0c066ba5c456bf0d2c150da4f /drivers/mmc | |
| parent | da68c4eb258cd9f3f0b8aeb7e46b8118bb6358b6 (diff) | |
sdio: sdhci support for suspend mode PM features
Tested with an XO v1.5 from OLPC.
Signed-off-by: Nicolas Pitre <nico@marvell.com>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/mmc')
| -rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 17 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 26 |
2 files changed, 31 insertions, 12 deletions
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 5c3a1767770a..dbf054315fe2 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -501,6 +501,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state) | |||
| 501 | { | 501 | { |
| 502 | struct sdhci_pci_chip *chip; | 502 | struct sdhci_pci_chip *chip; |
| 503 | struct sdhci_pci_slot *slot; | 503 | struct sdhci_pci_slot *slot; |
| 504 | mmc_pm_flag_t pm_flags = 0; | ||
| 504 | int i, ret; | 505 | int i, ret; |
| 505 | 506 | ||
| 506 | chip = pci_get_drvdata(pdev); | 507 | chip = pci_get_drvdata(pdev); |
| @@ -519,6 +520,8 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state) | |||
| 519 | sdhci_resume_host(chip->slots[i]->host); | 520 | sdhci_resume_host(chip->slots[i]->host); |
| 520 | return ret; | 521 | return ret; |
| 521 | } | 522 | } |
| 523 | |||
| 524 | pm_flags |= slot->host->mmc->pm_flags; | ||
| 522 | } | 525 | } |
| 523 | 526 | ||
| 524 | if (chip->fixes && chip->fixes->suspend) { | 527 | if (chip->fixes && chip->fixes->suspend) { |
| @@ -531,9 +534,15 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state) | |||
| 531 | } | 534 | } |
| 532 | 535 | ||
| 533 | pci_save_state(pdev); | 536 | pci_save_state(pdev); |
| 534 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | 537 | if (pm_flags & MMC_PM_KEEP_POWER) { |
| 535 | pci_disable_device(pdev); | 538 | if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) |
| 536 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 539 | pci_enable_wake(pdev, PCI_D3hot, 1); |
| 540 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 541 | } else { | ||
| 542 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | ||
| 543 | pci_disable_device(pdev); | ||
| 544 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
| 545 | } | ||
| 537 | 546 | ||
| 538 | return 0; | 547 | return 0; |
| 539 | } | 548 | } |
| @@ -653,6 +662,8 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( | |||
| 653 | goto unmap; | 662 | goto unmap; |
| 654 | } | 663 | } |
| 655 | 664 | ||
| 665 | host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; | ||
| 666 | |||
| 656 | ret = sdhci_add_host(host); | 667 | ret = sdhci_add_host(host); |
| 657 | if (ret) | 668 | if (ret) |
| 658 | goto remove; | 669 | goto remove; |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6c866b43b03c..d6ab62d539fb 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -174,20 +174,31 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) | |||
| 174 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); | 174 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static void sdhci_init(struct sdhci_host *host) | 177 | static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); |
| 178 | |||
| 179 | static void sdhci_init(struct sdhci_host *host, int soft) | ||
| 178 | { | 180 | { |
| 179 | sdhci_reset(host, SDHCI_RESET_ALL); | 181 | if (soft) |
| 182 | sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); | ||
| 183 | else | ||
| 184 | sdhci_reset(host, SDHCI_RESET_ALL); | ||
| 180 | 185 | ||
| 181 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, | 186 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, |
| 182 | SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | | 187 | SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | |
| 183 | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | | 188 | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | |
| 184 | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | | 189 | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | |
| 185 | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); | 190 | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); |
| 191 | |||
| 192 | if (soft) { | ||
| 193 | /* force clock reconfiguration */ | ||
| 194 | host->clock = 0; | ||
| 195 | sdhci_set_ios(host->mmc, &host->mmc->ios); | ||
| 196 | } | ||
| 186 | } | 197 | } |
| 187 | 198 | ||
| 188 | static void sdhci_reinit(struct sdhci_host *host) | 199 | static void sdhci_reinit(struct sdhci_host *host) |
| 189 | { | 200 | { |
| 190 | sdhci_init(host); | 201 | sdhci_init(host, 0); |
| 191 | sdhci_enable_card_detection(host); | 202 | sdhci_enable_card_detection(host); |
| 192 | } | 203 | } |
| 193 | 204 | ||
| @@ -1600,16 +1611,13 @@ int sdhci_resume_host(struct sdhci_host *host) | |||
| 1600 | if (ret) | 1611 | if (ret) |
| 1601 | return ret; | 1612 | return ret; |
| 1602 | 1613 | ||
| 1603 | sdhci_init(host); | 1614 | sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); |
| 1604 | mmiowb(); | 1615 | mmiowb(); |
| 1605 | 1616 | ||
| 1606 | ret = mmc_resume_host(host->mmc); | 1617 | ret = mmc_resume_host(host->mmc); |
| 1607 | if (ret) | ||
| 1608 | return ret; | ||
| 1609 | |||
| 1610 | sdhci_enable_card_detection(host); | 1618 | sdhci_enable_card_detection(host); |
| 1611 | 1619 | ||
| 1612 | return 0; | 1620 | return ret; |
| 1613 | } | 1621 | } |
| 1614 | 1622 | ||
| 1615 | EXPORT_SYMBOL_GPL(sdhci_resume_host); | 1623 | EXPORT_SYMBOL_GPL(sdhci_resume_host); |
| @@ -1864,7 +1872,7 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 1864 | if (ret) | 1872 | if (ret) |
| 1865 | goto untasklet; | 1873 | goto untasklet; |
| 1866 | 1874 | ||
| 1867 | sdhci_init(host); | 1875 | sdhci_init(host, 0); |
| 1868 | 1876 | ||
| 1869 | #ifdef CONFIG_MMC_DEBUG | 1877 | #ifdef CONFIG_MMC_DEBUG |
| 1870 | sdhci_dumpregs(host); | 1878 | sdhci_dumpregs(host); |
