aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Drake <dsd@laptop.org>2010-11-04 18:20:39 -0400
committerChris Ball <cjb@laptop.org>2010-11-07 16:45:11 -0500
commit5f619704d18b93869d045abc49e09cdba109b04b (patch)
tree50d523926d50bac76448fea6ab25c1e118537e06
parent14d4031d21d8a63ad84e5ab9198d0503efabc780 (diff)
mmc: sdhci: Properly enable SDIO IRQ wakeups
A little more work was needed for SDIO IRQ wakeups to be functional. Wake-on-WLAN on the SD WiFi adapter in the XO-1.5 laptop is now working. Signed-off-by: Daniel Drake <dsd@laptop.org> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/host/sdhci-pci.c11
-rw-r--r--drivers/mmc/host/sdhci.c10
-rw-r--r--drivers/mmc/host/sdhci.h4
3 files changed, 23 insertions, 2 deletions
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 55746bac2f44..d196e77a93dc 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -637,6 +637,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
637{ 637{
638 struct sdhci_pci_chip *chip; 638 struct sdhci_pci_chip *chip;
639 struct sdhci_pci_slot *slot; 639 struct sdhci_pci_slot *slot;
640 mmc_pm_flag_t slot_pm_flags;
640 mmc_pm_flag_t pm_flags = 0; 641 mmc_pm_flag_t pm_flags = 0;
641 int i, ret; 642 int i, ret;
642 643
@@ -657,7 +658,11 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
657 return ret; 658 return ret;
658 } 659 }
659 660
660 pm_flags |= slot->host->mmc->pm_flags; 661 slot_pm_flags = slot->host->mmc->pm_flags;
662 if (slot_pm_flags & MMC_PM_WAKE_SDIO_IRQ)
663 sdhci_enable_irq_wakeups(slot->host);
664
665 pm_flags |= slot_pm_flags;
661 } 666 }
662 667
663 if (chip->fixes && chip->fixes->suspend) { 668 if (chip->fixes && chip->fixes->suspend) {
@@ -671,8 +676,10 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
671 676
672 pci_save_state(pdev); 677 pci_save_state(pdev);
673 if (pm_flags & MMC_PM_KEEP_POWER) { 678 if (pm_flags & MMC_PM_KEEP_POWER) {
674 if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) 679 if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
680 pci_pme_active(pdev, true);
675 pci_enable_wake(pdev, PCI_D3hot, 1); 681 pci_enable_wake(pdev, PCI_D3hot, 1);
682 }
676 pci_set_power_state(pdev, PCI_D3hot); 683 pci_set_power_state(pdev, PCI_D3hot);
677 } else { 684 } else {
678 pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); 685 pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 782c0ee3c925..154cbf83c1ab 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1681,6 +1681,16 @@ int sdhci_resume_host(struct sdhci_host *host)
1681 1681
1682EXPORT_SYMBOL_GPL(sdhci_resume_host); 1682EXPORT_SYMBOL_GPL(sdhci_resume_host);
1683 1683
1684void sdhci_enable_irq_wakeups(struct sdhci_host *host)
1685{
1686 u8 val;
1687 val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
1688 val |= SDHCI_WAKE_ON_INT;
1689 sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
1690}
1691
1692EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups);
1693
1684#endif /* CONFIG_PM */ 1694#endif /* CONFIG_PM */
1685 1695
1686/*****************************************************************************\ 1696/*****************************************************************************\
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index b7b8a3b28b01..d52a7163b97a 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -87,6 +87,9 @@
87#define SDHCI_BLOCK_GAP_CONTROL 0x2A 87#define SDHCI_BLOCK_GAP_CONTROL 0x2A
88 88
89#define SDHCI_WAKE_UP_CONTROL 0x2B 89#define SDHCI_WAKE_UP_CONTROL 0x2B
90#define SDHCI_WAKE_ON_INT 0x01
91#define SDHCI_WAKE_ON_INSERT 0x02
92#define SDHCI_WAKE_ON_REMOVE 0x04
90 93
91#define SDHCI_CLOCK_CONTROL 0x2C 94#define SDHCI_CLOCK_CONTROL 0x2C
92#define SDHCI_DIVIDER_SHIFT 8 95#define SDHCI_DIVIDER_SHIFT 8
@@ -317,6 +320,7 @@ extern void sdhci_remove_host(struct sdhci_host *host, int dead);
317#ifdef CONFIG_PM 320#ifdef CONFIG_PM
318extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state); 321extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state);
319extern int sdhci_resume_host(struct sdhci_host *host); 322extern int sdhci_resume_host(struct sdhci_host *host);
323extern void sdhci_enable_irq_wakeups(struct sdhci_host *host);
320#endif 324#endif
321 325
322#endif /* __SDHCI_HW_H */ 326#endif /* __SDHCI_HW_H */