Linux-mediatek Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Chaotian Jing <chaotian.jing-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
To: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Matthias Brugger
	<matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	Chris Ball <chris-OsFVWbfNK3isTnJN9+BGXg@public.gmane.org>,
	Ulf Hansson <ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>,
	James Liao <jamesjj.liao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>,
	srv_heupstream-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
	Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Hongzhou Yang
	<hongzhou.yang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>,
	Catalin Marinas <catalin.marinas-5wv7dgnIgG8@public.gmane.org>,
	bin.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>,
	linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	Chaotian Jing
	<chaotian.jing-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>,
	Sascha Hauer <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>,
	"Joe.C" <yingjoe.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>,
	Eddie Huang <eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Subject: [PATCH v4 3/7] mmc: mediatek: Add PM support for MMC driver
Date: Tue, 19 May 2015 14:36:47 +0800	[thread overview]
Message-ID: <1432017411-2996-4-git-send-email-chaotian.jing@mediatek.com> (raw)
In-Reply-To: <1432017411-2996-1-git-send-email-chaotian.jing-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>

Add PM support for Mediatek MMC driver
Save/restore registers when PM

Signed-off-by: Chaotian Jing <chaotian.jing-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
 drivers/mmc/host/mtk-sd.c | 99 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 95 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 26e9590..c0b2e2d 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -22,6 +22,7 @@
 #include <linux/of_gpio.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spinlock.h>
 
@@ -212,6 +213,7 @@
 #define MSDC_ASYNC_FLAG (0x1 << 1)
 #define MSDC_MMAP_FLAG (0x1 << 2)
 
+#define MTK_MMC_AUTOSUSPEND_DELAY	50
 #define CMD_TIMEOUT         (HZ/10 * 5)	/* 100ms x5 */
 #define DAT_TIMEOUT         (HZ    * 5)	/* 1000ms x5 */
 
@@ -254,6 +256,15 @@ struct msdc_dma {
 	dma_addr_t bd_addr;	/* the physical address of bd array */
 };
 
+struct msdc_save_para {
+	u32 msdc_cfg;
+	u32 iocon;
+	u32 sdc_cfg;
+	u32 pad_tune;
+	u32 patch_bit0;
+	u32 patch_bit1;
+};
+
 struct msdc_host {
 	struct device *dev;
 	struct mmc_host *mmc;	/* mmc structure */
@@ -287,6 +298,8 @@ struct msdc_host {
 	bool vqmmc_enabled;
 	bool sclk_enabled;	/* source clock enabled */
 	bool hclk_enabled;	/* Hclk enabled */
+	bool in_suspend;	/* used for apply restore regs */
+	struct msdc_save_para save_para; /* used when gate HCLK */
 };
 
 static void sdr_set_bits(void __iomem *reg, u32 bs)
@@ -459,6 +472,30 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks)
 	sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, timeout);
 }
 
+static void msdc_save_reg(struct msdc_host *host)
+{
+	host->save_para.msdc_cfg = readl(host->base + MSDC_CFG);
+	host->save_para.iocon = readl(host->base + MSDC_IOCON);
+	host->save_para.sdc_cfg = readl(host->base + SDC_CFG);
+	host->save_para.pad_tune = readl(host->base + MSDC_PAD_TUNE);
+	host->save_para.patch_bit0 = readl(host->base + MSDC_PATCH_BIT);
+	host->save_para.patch_bit1 = readl(host->base + MSDC_PATCH_BIT1);
+	host->in_suspend = true;
+}
+
+static void msdc_restore_reg(struct msdc_host *host)
+{
+	if (host->in_suspend == false)
+		return;
+	writel(host->save_para.msdc_cfg, host->base + MSDC_CFG);
+	writel(host->save_para.iocon, host->base + MSDC_IOCON);
+	writel(host->save_para.sdc_cfg, host->base + SDC_CFG);
+	writel(host->save_para.pad_tune, host->base + MSDC_PAD_TUNE);
+	writel(host->save_para.patch_bit0, host->base + MSDC_PATCH_BIT);
+	writel(host->save_para.patch_bit1, host->base + MSDC_PATCH_BIT1);
+	host->in_suspend = false;
+}
+
 static void msdc_disable_src_clk(struct msdc_host *host)
 {
 	if (host->sclk_enabled) {
@@ -479,6 +516,10 @@ static void msdc_enable_src_clk(struct msdc_host *host)
 
 static void msdc_gate_clock(struct msdc_host *host)
 {
+	/* Save register first, only when clk is on */
+	if (host->sclk_enabled)
+		msdc_save_reg(host);
+
 	msdc_disable_src_clk(host);
 	if (!IS_ERR(host->h_clk) && host->hclk_enabled) {
 		clk_disable_unprepare(host->h_clk);
@@ -493,6 +534,8 @@ static void msdc_ungate_clock(struct msdc_host *host)
 		host->hclk_enabled = true;
 	}
 	msdc_enable_src_clk(host);
+	/* Then restore register */
+	msdc_restore_reg(host);
 }
 
 static void msdc_set_mclk(struct msdc_host *host, int ddr, u32 hz)
@@ -710,6 +753,9 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
 	if (mrq->data)
 		msdc_unprepare_data(host, mrq);
 	mmc_request_done(host->mmc, mrq);
+
+	pm_runtime_mark_last_busy(host->dev);
+	pm_runtime_put_autosuspend(host->dev);
 }
 
 /* returns true if command is fully handled; returns false otherwise */
@@ -866,6 +912,8 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
 		WARN_ON(host->mrq);
 	spin_unlock_irqrestore(&host->lock, flags);
 
+	pm_runtime_get_sync(host->dev);
+
 	if (mrq->data)
 		msdc_prepare_data(host, mrq);
 
@@ -1130,7 +1178,8 @@ static void msdc_init_hw(struct msdc_host *host)
 	sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1);
 	writel(0xffff0089, host->base + MSDC_PATCH_BIT1);
 	/* Configure to enable SDIO mode.
-	   it's must otherwise sdio cmd5 failed */
+	 * it's must otherwise sdio cmd5 failed
+	 */
 	sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO);
 
 	/* disable detect SDIO device interrupt function */
@@ -1185,6 +1234,8 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	int ret;
 	u32 ddr = 0;
 
+	pm_runtime_get_sync(host->dev);
+
 	if (ios->timing == MMC_TIMING_UHS_DDR50 ||
 			ios->timing == MMC_TIMING_MMC_DDR52)
 		ddr = 1;
@@ -1200,7 +1251,7 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 					ios->vdd);
 			if (ret) {
 				dev_err(host->dev, "Failed to set vmmc power!\n");
-				return;
+				goto end;
 			}
 		}
 		break;
@@ -1234,6 +1285,10 @@ static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	if (host->mclk != ios->clock || host->ddr != ddr)
 		msdc_set_mclk(host, ddr, ios->clock);
+
+end:
+	pm_runtime_mark_last_busy(host->dev);
+	pm_runtime_put_autosuspend(host->dev);
 }
 
 static struct mmc_host_ops mt_msdc_ops = {
@@ -1355,12 +1410,18 @@ static int msdc_drv_probe(struct platform_device *pdev)
 	if (ret)
 		goto release;
 
+	pm_runtime_set_active(host->dev);
+	pm_runtime_set_autosuspend_delay(host->dev, MTK_MMC_AUTOSUSPEND_DELAY);
+	pm_runtime_use_autosuspend(host->dev);
+	pm_runtime_enable(host->dev);
 	ret = mmc_add_host(mmc);
+
 	if (ret)
-		goto release;
+		goto end;
 
 	return 0;
-
+end:
+	pm_runtime_disable(host->dev);
 release:
 	platform_set_drvdata(pdev, NULL);
 	msdc_deinit_hw(host);
@@ -1388,10 +1449,15 @@ static int msdc_drv_remove(struct platform_device *pdev)
 	mmc = platform_get_drvdata(pdev);
 	host = mmc_priv(mmc);
 
+	pm_runtime_get_sync(host->dev);
+
 	platform_set_drvdata(pdev, NULL);
 	mmc_remove_host(host->mmc);
 	msdc_deinit_hw(host);
+	msdc_gate_clock(host);
 
+	pm_runtime_disable(host->dev);
+	pm_runtime_put_noidle(host->dev);
 	dma_free_coherent(&pdev->dev,
 			sizeof(struct mt_gpdma_desc),
 			host->dma.gpd, host->dma.gpd_addr);
@@ -1403,6 +1469,30 @@ static int msdc_drv_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int msdc_runtime_suspend(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct msdc_host *host = mmc_priv(mmc);
+
+	msdc_gate_clock(host);
+	return 0;
+}
+
+static int msdc_runtime_resume(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct msdc_host *host = mmc_priv(mmc);
+
+	msdc_ungate_clock(host);
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops msdc_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(msdc_runtime_suspend, msdc_runtime_resume, NULL)
+};
+
 static const struct of_device_id msdc_of_ids[] = {
 	{   .compatible = "mediatek,mt8135-mmc", },
 	{}
@@ -1414,6 +1504,7 @@ static struct platform_driver mt_msdc_driver = {
 	.driver = {
 		.name = "mtk-msdc",
 		.of_match_table = msdc_of_ids,
+		.pm = &msdc_dev_pm_ops,
 	},
 };
 
-- 
1.8.1.1.dirty

  parent reply	other threads:[~2015-05-19  6:36 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-19  6:36 [PATCH v4 0/7] Add Mediatek MMC driver Chaotian Jing
     [not found] ` <1432017411-2996-1-git-send-email-chaotian.jing-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2015-05-19  6:36   ` [PATCH v4 1/7] mmc: dt-bindings: add Mediatek MMC bindings Chaotian Jing
     [not found]     ` <1432017411-2996-2-git-send-email-chaotian.jing-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2015-05-19  9:41       ` Ulf Hansson
     [not found]         ` <CAPDyKFq+YAz2pt1820YnqWaVKO6sn5eB+NxuM2dhP236FSKa9g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-05-26  6:27           ` Chaotian Jing
2015-05-19  6:36   ` [PATCH v4 2/7] mmc: mediatek: Add Mediatek MMC driver Chaotian Jing
     [not found]     ` <1432017411-2996-3-git-send-email-chaotian.jing-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
2015-05-19 10:27       ` Ulf Hansson
     [not found]         ` <CAPDyKFo5788uRqAaXUZ-OiS1XF8NPmg4tn2ipZNJdx4dci+KMQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-05-22  8:40           ` Chaotian Jing
2015-05-22 12:51             ` Ulf Hansson
     [not found]               ` <CAPDyKFpWCvJXL-W5P83ucBM2-b5cDFEtSLnN6J6WLyR_9CuvWw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-05-26  6:16                 ` Chaotian Jing
2015-05-26 12:33                   ` Ulf Hansson
     [not found]                     ` <CAPDyKFrNQ6E4cU1_gK56ZNYgb=9EzHoJ=vXyraYoKNnRL=Umyg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-05-27 11:34                       ` Chaotian Jing
2015-06-04  7:32                         ` Ulf Hansson
2015-05-19 11:15     ` Sascha Hauer
     [not found]       ` <20150519111558.GD6325-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2015-06-04  2:54         ` Chaotian Jing
2015-06-04  9:02           ` Sascha Hauer
2015-05-19 11:19     ` Russell King - ARM Linux
     [not found]       ` <20150519111936.GC2067-l+eeeJia6m9vn6HldHNs0ANdhmdF6hFW@public.gmane.org>
2015-05-20  9:14         ` Chaotian Jing
2015-05-19  6:36   ` Chaotian Jing [this message]
2015-05-19 10:41     ` [PATCH v4 3/7] mmc: mediatek: Add PM support for " Ulf Hansson
2015-05-19 11:04     ` Sascha Hauer
2015-05-19 11:55       ` Ulf Hansson
2015-05-19  6:36   ` [PATCH v4 4/7] arm64: dts: mediatek: Add MT8173 MMC dts Chaotian Jing
2015-05-19  6:36   ` [PATCH v4 5/7] arm64: mediatek: Add Mediatek MMC support in defconfig Chaotian Jing
2015-05-19  6:36   ` [PATCH v4 6/7] ARM: mediatek: dts: Add emmc support to mt8135 Chaotian Jing
2015-05-19  6:36   ` [PATCH v4 7/7] ARM: multi_v7_defconfig: Enable Mediatek MMC support multi-v7 Chaotian Jing

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1432017411-2996-4-git-send-email-chaotian.jing@mediatek.com \
    --to=chaotian.jing-nus5lvnupcjwk0htik3j/w@public.gmane.org \
    --cc=arnd-r2nGTMty4D4@public.gmane.org \
    --cc=bin.zhang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
    --cc=catalin.marinas-5wv7dgnIgG8@public.gmane.org \
    --cc=chris-OsFVWbfNK3isTnJN9+BGXg@public.gmane.org \
    --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=eddie.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
    --cc=hongzhou.yang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
    --cc=jamesjj.liao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
    --cc=kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org \
    --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=linux-mmc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=mark.rutland-5wv7dgnIgG8@public.gmane.org \
    --cc=matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=srv_heupstream-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
    --cc=ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
    --cc=will.deacon-5wv7dgnIgG8@public.gmane.org \
    --cc=yingjoe.chen-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox