]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/mmc/host/davinci_mmc.c
mmc: remove the "state" argument to mmc_suspend_host()
[net-next-2.6.git] / drivers / mmc / host / davinci_mmc.c
index 547d29c31b40d8f5525ccaeba023e7f1e1b9a6c4..33d9f1b00862f805aca98acf72c497d91239be02 100644 (file)
@@ -171,6 +171,7 @@ struct mmc_davinci_host {
 #define DAVINCI_MMC_DATADIR_READ       1
 #define DAVINCI_MMC_DATADIR_WRITE      2
        unsigned char data_dir;
+       unsigned char suspended;
 
        /* buffer is used during PIO of one scatterlist segment, and
         * is updated along with buffer_bytes_left.  bytes_left applies
@@ -909,19 +910,26 @@ static void mmc_davinci_cmd_done(struct mmc_davinci_host *host,
        }
 }
 
-static void
-davinci_abort_data(struct mmc_davinci_host *host, struct mmc_data *data)
+static inline void mmc_davinci_reset_ctrl(struct mmc_davinci_host *host,
+                                                               int val)
 {
        u32 temp;
 
-       /* reset command and data state machines */
        temp = readl(host->base + DAVINCI_MMCCTL);
-       writel(temp | MMCCTL_CMDRST | MMCCTL_DATRST,
-               host->base + DAVINCI_MMCCTL);
+       if (val)        /* reset */
+               temp |= MMCCTL_CMDRST | MMCCTL_DATRST;
+       else            /* enable */
+               temp &= ~(MMCCTL_CMDRST | MMCCTL_DATRST);
 
-       temp &= ~(MMCCTL_CMDRST | MMCCTL_DATRST);
-       udelay(10);
        writel(temp, host->base + DAVINCI_MMCCTL);
+       udelay(10);
+}
+
+static void
+davinci_abort_data(struct mmc_davinci_host *host, struct mmc_data *data)
+{
+       mmc_davinci_reset_ctrl(host, 1);
+       mmc_davinci_reset_ctrl(host, 0);
 }
 
 static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
@@ -1125,15 +1133,8 @@ static inline void mmc_davinci_cpufreq_deregister(struct mmc_davinci_host *host)
 #endif
 static void __init init_mmcsd_host(struct mmc_davinci_host *host)
 {
-       /* DAT line portion is diabled and in reset state */
-       writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_DATRST,
-               host->base + DAVINCI_MMCCTL);
 
-       /* CMD line portion is diabled and in reset state */
-       writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_CMDRST,
-               host->base + DAVINCI_MMCCTL);
-
-       udelay(10);
+       mmc_davinci_reset_ctrl(host, 1);
 
        writel(0, host->base + DAVINCI_MMCCLK);
        writel(MMCCLK_CLKEN, host->base + DAVINCI_MMCCLK);
@@ -1141,12 +1142,7 @@ static void __init init_mmcsd_host(struct mmc_davinci_host *host)
        writel(0x1FFF, host->base + DAVINCI_MMCTOR);
        writel(0xFFFF, host->base + DAVINCI_MMCTOD);
 
-       writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_DATRST,
-               host->base + DAVINCI_MMCCTL);
-       writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_CMDRST,
-               host->base + DAVINCI_MMCCTL);
-
-       udelay(10);
+       mmc_davinci_reset_ctrl(host, 0);
 }
 
 static int __init davinci_mmcsd_probe(struct platform_device *pdev)
@@ -1337,32 +1333,65 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int davinci_mmcsd_suspend(struct platform_device *pdev, pm_message_t msg)
+static int davinci_mmcsd_suspend(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct mmc_davinci_host *host = platform_get_drvdata(pdev);
+       int ret;
 
-       return mmc_suspend_host(host->mmc, msg);
+       mmc_host_enable(host->mmc);
+       ret = mmc_suspend_host(host->mmc);
+       if (!ret) {
+               writel(0, host->base + DAVINCI_MMCIM);
+               mmc_davinci_reset_ctrl(host, 1);
+               mmc_host_disable(host->mmc);
+               clk_disable(host->clk);
+               host->suspended = 1;
+       } else {
+               host->suspended = 0;
+               mmc_host_disable(host->mmc);
+       }
+
+       return ret;
 }
 
-static int davinci_mmcsd_resume(struct platform_device *pdev)
+static int davinci_mmcsd_resume(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct mmc_davinci_host *host = platform_get_drvdata(pdev);
+       int ret;
+
+       if (!host->suspended)
+               return 0;
 
-       return mmc_resume_host(host->mmc);
+       clk_enable(host->clk);
+       mmc_host_enable(host->mmc);
+
+       mmc_davinci_reset_ctrl(host, 0);
+       ret = mmc_resume_host(host->mmc);
+       if (!ret)
+               host->suspended = 0;
+
+       return ret;
 }
+
+static const struct dev_pm_ops davinci_mmcsd_pm = {
+       .suspend        = davinci_mmcsd_suspend,
+       .resume         = davinci_mmcsd_resume,
+};
+
+#define davinci_mmcsd_pm_ops (&davinci_mmcsd_pm)
 #else
-#define davinci_mmcsd_suspend  NULL
-#define davinci_mmcsd_resume   NULL
+#define davinci_mmcsd_pm_ops NULL
 #endif
 
 static struct platform_driver davinci_mmcsd_driver = {
        .driver         = {
                .name   = "davinci_mmc",
                .owner  = THIS_MODULE,
+               .pm     = davinci_mmcsd_pm_ops,
        },
        .remove         = __exit_p(davinci_mmcsd_remove),
-       .suspend        = davinci_mmcsd_suspend,
-       .resume         = davinci_mmcsd_resume,
 };
 
 static int __init davinci_mmcsd_init(void)