]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
sdhci: arasan: Add runtime PM support
authorManish Narani <manish.narani@xilinx.com>
Thu, 12 Apr 2018 12:30:34 +0000 (18:00 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Wed, 2 May 2018 06:29:56 +0000 (08:29 +0200)
This patch adds runtime PM support in Arasan SD driver.

Signed-off-by: Manish Narani <manish.narani@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/mmc/host/sdhci-of-arasan.c

index ce645e9f39574ab7e5e8799701ba502b8d3e03a9..9b93f0d50e5c2fda6653c5291c280b2d89b70811 100644 (file)
@@ -493,6 +493,75 @@ static const struct sdhci_pltfm_data sdhci_arasan_pdata = {
                        SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
 };
 
+#ifdef CONFIG_PM
+/**
+ * sdhci_arasan_runtime_suspend - Suspend method for the driver
+ * @dev:       Address of the device structure
+ * Put the device in a low power state.
+ *
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_arasan_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sdhci_host *host = platform_get_drvdata(pdev);
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+       int ret;
+
+       ret = sdhci_runtime_suspend_host(host);
+       if (ret)
+               return ret;
+
+       if (host->tuning_mode != SDHCI_TUNING_MODE_3)
+               mmc_retune_needed(host->mmc);
+
+       clk_disable(pltfm_host->clk);
+       clk_disable(sdhci_arasan->clk_ahb);
+
+       return 0;
+}
+
+/**
+ * sdhci_arasan_runtime_resume - Resume method for the driver
+ * @dev:       Address of the device structure
+ * Resume operation after suspend
+ *
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_arasan_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sdhci_host *host = platform_get_drvdata(pdev);
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+       int ret;
+
+       ret = clk_enable(sdhci_arasan->clk_ahb);
+       if (ret) {
+               dev_err(dev, "Cannot enable AHB clock.\n");
+               return ret;
+       }
+
+       ret = clk_enable(pltfm_host->clk);
+       if (ret) {
+               dev_err(dev, "Cannot enable SD clock.\n");
+               return ret;
+       }
+
+       ret = sdhci_runtime_resume_host(host);
+       if (ret)
+               goto out;
+
+       return 0;
+out:
+       clk_disable(pltfm_host->clk);
+       clk_disable(sdhci_arasan->clk_ahb);
+
+       return ret;
+}
+#endif /* ! CONFIG_PM */
+
 #ifdef CONFIG_PM_SLEEP
 /**
  * sdhci_arasan_suspend - Suspend method for the driver
@@ -572,8 +641,11 @@ static int sdhci_arasan_resume(struct device *dev)
 }
 #endif /* ! CONFIG_PM_SLEEP */
 
-static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend,
-                        sdhci_arasan_resume);
+static const struct dev_pm_ops sdhci_arasan_dev_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(sdhci_arasan_suspend, sdhci_arasan_resume)
+       SET_RUNTIME_PM_OPS(sdhci_arasan_runtime_suspend,
+                          sdhci_arasan_runtime_resume, NULL)
+};
 
 static const struct of_device_id sdhci_arasan_of_match[] = {
        /* SoC-specific compatible strings w/ soc_ctl_map */
@@ -953,6 +1025,13 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
        if (ret)
                goto err_add_host;
 
+       pm_runtime_set_active(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
+       pm_runtime_mark_last_busy(&pdev->dev);
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_forbid(&pdev->dev);
+
        return 0;
 
 err_add_host: