mmc: dw_mmc: Add sdio power bindings
authorAbhilash Kesavan <a.kesavan@samsung.com>
Mon, 19 Nov 2012 04:56:21 +0000 (10:26 +0530)
committerChris Ball <cjb@laptop.org>
Thu, 6 Dec 2012 18:54:54 +0000 (13:54 -0500)
Add dt-based retrieval of host sdio pm capabilities. Based on
the dt based discovery do a bus init in the resume function.

Signed-off-by: Olof Johansson <olofj@chromium.org>
Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/host/dw_mmc.c
include/linux/mmc/dw_mmc.h

index 5b4134811c909ebb88798f3df155006b7c65d562..73420296b2688bfa309d971307f0d5a27fa6cabc 100644 (file)
@@ -617,13 +617,13 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
                cmd, arg, cmd_status);
 }
 
-static void dw_mci_setup_bus(struct dw_mci_slot *slot)
+static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
 {
        struct dw_mci *host = slot->host;
        u32 div;
        u32 clk_en_a;
 
-       if (slot->clock != host->current_speed) {
+       if (slot->clock != host->current_speed || force_clkinit) {
                div = host->bus_hz / slot->clock;
                if (host->bus_hz % slot->clock && host->bus_hz > slot->clock)
                        /*
@@ -684,7 +684,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
                host->pdata->select_slot(slot->id);
 
        /* Slot specific timing and width adjustment */
-       dw_mci_setup_bus(slot);
+       dw_mci_setup_bus(slot, false);
 
        host->cur_slot = slot;
        host->mrq = mrq;
@@ -1850,6 +1850,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        if (host->pdata->caps)
                mmc->caps = host->pdata->caps;
 
+       if (host->pdata->pm_caps)
+               mmc->pm_caps = host->pdata->pm_caps;
+
        if (host->dev->of_node) {
                ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
                if (ctrl_id < 0)
@@ -2072,6 +2075,12 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
                        return ERR_PTR(ret);
        }
 
+       if (of_find_property(np, "keep-power-in-suspend", NULL))
+               pdata->pm_caps |= MMC_PM_KEEP_POWER;
+
+       if (of_find_property(np, "enable-sdio-wakeup", NULL))
+               pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+
        return pdata;
 }
 
@@ -2411,6 +2420,11 @@ int dw_mci_resume(struct dw_mci *host)
                struct dw_mci_slot *slot = host->slot[i];
                if (!slot)
                        continue;
+               if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
+                       dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
+                       dw_mci_setup_bus(slot, true);
+               }
+
                ret = mmc_resume_host(host->slot[i]->mmc);
                if (ret < 0)
                        return ret;
index a5498dce1cb5fe5693e64aa6757c5d08add213c5..34be4f47293caa906ee7a8d5d2148897a4adff4a 100644 (file)
@@ -231,6 +231,7 @@ struct dw_mci_board {
 
        u32 caps;       /* Capabilities */
        u32 caps2;      /* More capabilities */
+       u32 pm_caps;    /* PM capabilities */
        /*
         * Override fifo depth. If 0, autodetect it from the FIFOTH register,
         * but note that this may not be reliable after a bootloader has used