mmc: sdio: bind acpi with sdio function device
authorAaron Lu <aaron.lu@intel.com>
Tue, 5 Mar 2013 03:24:52 +0000 (11:24 +0800)
committerChris Ball <cjb@laptop.org>
Fri, 22 Mar 2013 16:26:54 +0000 (12:26 -0400)
ACPI spec 5 defined the _ADR encoding for sdio bus as:
High word - slot number (0 based)
Low word  - function number

This patch adds support for binding sdio function device with acpi node,
and if successful, involve acpi into its power management.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/core/sdio_bus.c
drivers/mmc/host/sdhci-pci.c
include/linux/mmc/host.h

index 5e57048e2c1d2c0fbb202600f9bfa45ffa0355c4..8d6bb182183490ad3a4e62fd0710cb5ff21683bb 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/acpi.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -299,6 +300,19 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card)
        return func;
 }
 
+#ifdef CONFIG_ACPI
+static void sdio_acpi_set_handle(struct sdio_func *func)
+{
+       struct mmc_host *host = func->card->host;
+       u64 addr = (host->slotno << 16) | func->num;
+
+       ACPI_HANDLE_SET(&func->dev,
+                       acpi_get_child(ACPI_HANDLE(host->parent), addr));
+}
+#else
+static inline void sdio_acpi_set_handle(struct sdio_func *func) {}
+#endif
+
 /*
  * Register a new SDIO function with the driver model.
  */
@@ -308,9 +322,12 @@ int sdio_add_func(struct sdio_func *func)
 
        dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
 
+       sdio_acpi_set_handle(func);
        ret = device_add(&func->dev);
-       if (ret == 0)
+       if (ret == 0) {
                sdio_func_set_present(func);
+               acpi_dev_pm_attach(&func->dev, false);
+       }
 
        return ret;
 }
@@ -326,6 +343,7 @@ void sdio_remove_func(struct sdio_func *func)
        if (!sdio_func_present(func))
                return;
 
+       acpi_dev_pm_detach(&func->dev, false);
        device_del(&func->dev);
        put_device(&func->dev);
 }
index c7ccf3034dadee35cc24347bdd2958fcdf22badf..3dee22d098e904c51566671346d4e9a5cae4fad5 100644 (file)
@@ -1279,6 +1279,7 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
        }
 
        host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
+       host->mmc->slotno = slotno;
 
        ret = sdhci_add_host(host);
        if (ret)
index d6f20cc6415e1feb50278f59551f6dbbe345a8de..17d714801e94c600722144a422bb7240d33b37b3 100644 (file)
@@ -361,6 +361,8 @@ struct mmc_host {
 
        unsigned int            actual_clock;   /* Actual HC clock rate */
 
+       unsigned int            slotno; /* used for sdio acpi binding */
+
        unsigned long           private[0] ____cacheline_aligned;
 };