From patchwork Wed Dec 20 10:50:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 10125485 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 135766019C for ; Wed, 20 Dec 2017 10:52:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E3666296DC for ; Wed, 20 Dec 2017 10:52:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D85CE296F2; Wed, 20 Dec 2017 10:52:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3E46A296DC for ; Wed, 20 Dec 2017 10:52:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=6yPR0x0SRNL0BKDsnMyMr1Kfs1I4KA4tUSKv9P61yEg=; b=U1ORKZr68zADgYvJooCcIdjrUE Hsu6w7QeSWZJn7isfk5fj7gqShrXpFmRgKy+np4c8Ippg8dYoVTnj52CKDVcgOB9oN268spjMOVdq rr49glxctKJMlweKmp6aPo462+0MaTrSAcsZOUO/zCFwxgCCox5P9k5A7vtXwEH1U7Y/LOAFguuF5 wEUMT8aq5NXOhEH78rSvh/Hbx65ek/CK0LmTyS9gnp+beB8cFv6hhTqlRQ89gnqfVWJ3WjIlFJJm7 FxRrDvI7zPleUGkkrhicGokamQE6NGteUSoM1znwLVPdQgJC8NfQj6b2AxUPpU0m6kmcevdxIvYOY nKgfMlFA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1eRbyq-0001US-Tn; Wed, 20 Dec 2017 10:52:08 +0000 Received: from mail.free-electrons.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1eRbxl-0000X2-Ff for linux-arm-kernel@lists.infradead.org; Wed, 20 Dec 2017 10:51:09 +0000 Received: by mail.free-electrons.com (Postfix, from userid 110) id 5A0B820949; Wed, 20 Dec 2017 11:50:51 +0100 (CET) Received: from localhost (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.free-electrons.com (Postfix) with ESMTPSA id C18CC207F3; Wed, 20 Dec 2017 11:50:39 +0100 (CET) From: Maxime Ripard To: Chen-Yu Tsai , Maxime Ripard , Ulf Hansson Subject: [PATCH 2/2] mmc: sunxi: Add runtime_pm support Date: Wed, 20 Dec 2017 11:50:35 +0100 Message-Id: <412579f183c42f6fe2ea04f294dfb788be5e4875.1513766964.git-series.maxime.ripard@free-electrons.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: References: In-Reply-To: References: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171220_025101_907369_12219C4C X-CRM114-Status: GOOD ( 14.64 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-mmc@vger.kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP So far, even if our card was not in use, we didn't shut down our main clock, which meant that it was still output on the MMC bus. While this obviously means that we could save some power there, it also created issues when it comes with EMC control since we'll have a perfect peak at the card clock rate. Let's implement runtime_pm with autosuspend so that we will shut down the clock when it's not been in use for quite some time. Signed-off-by: Maxime Ripard --- drivers/mmc/host/sunxi-mmc.c | 90 ++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 3ce46ebd3488..c6a0bd0e0476 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -1217,29 +1218,11 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, return ret; } - ret = clk_prepare_enable(host->clk_mmc); - if (ret) { - dev_err(&pdev->dev, "Enable mmc clk err %d\n", ret); - goto error_disable_clk_ahb; - } - - ret = clk_prepare_enable(host->clk_output); - if (ret) { - dev_err(&pdev->dev, "Enable output clk err %d\n", ret); - goto error_disable_clk_mmc; - } - - ret = clk_prepare_enable(host->clk_sample); - if (ret) { - dev_err(&pdev->dev, "Enable sample clk err %d\n", ret); - goto error_disable_clk_output; - } - if (!IS_ERR(host->reset)) { ret = reset_control_reset(host->reset); if (ret) { dev_err(&pdev->dev, "reset err %d\n", ret); - goto error_disable_clk_sample; + goto error_disable_clk_ahb; } } @@ -1258,12 +1241,6 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, error_assert_reset: if (!IS_ERR(host->reset)) reset_control_assert(host->reset); -error_disable_clk_sample: - clk_disable_unprepare(host->clk_sample); -error_disable_clk_output: - clk_disable_unprepare(host->clk_output); -error_disable_clk_mmc: - clk_disable_unprepare(host->clk_mmc); error_disable_clk_ahb: clk_disable_unprepare(host->clk_ahb); return ret; @@ -1280,6 +1257,7 @@ static int sunxi_mmc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "mmc alloc host failed\n"); return -ENOMEM; } + platform_set_drvdata(pdev, mmc); host = mmc_priv(mmc); host->mmc = mmc; @@ -1340,12 +1318,16 @@ static int sunxi_mmc_probe(struct platform_device *pdev) if (ret) goto error_free_dma; + pm_runtime_set_autosuspend_delay(&pdev->dev, 50); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); + ret = mmc_add_host(mmc); if (ret) goto error_free_dma; dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq); - platform_set_drvdata(pdev, mmc); + return 0; error_free_dma: @@ -1361,27 +1343,75 @@ static int sunxi_mmc_remove(struct platform_device *pdev) struct sunxi_mmc_host *host = mmc_priv(mmc); mmc_remove_host(mmc); + pm_runtime_force_suspend(&pdev->dev); disable_irq(host->irq); sunxi_mmc_reset_host(host); if (!IS_ERR(host->reset)) reset_control_assert(host->reset); - clk_disable_unprepare(host->clk_sample); + dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); + mmc_free_host(mmc); + + return 0; +} + +static int sunxi_mmc_runtime_resume(struct device *dev) +{ + struct mmc_host *mmc = dev_get_drvdata(dev); + struct sunxi_mmc_host *host = mmc_priv(mmc); + int ret; + + ret = clk_prepare_enable(host->clk_mmc); + if (ret) { + dev_err(dev, "Enable mmc clk err %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(host->clk_output); + if (ret) { + dev_err(dev, "Enable output clk err %d\n", ret); + goto error_disable_clk_mmc; + } + + ret = clk_prepare_enable(host->clk_sample); + if (ret) { + dev_err(dev, "Enable sample clk err %d\n", ret); + goto error_disable_clk_output; + } + + return 0; + +error_disable_clk_output: clk_disable_unprepare(host->clk_output); +error_disable_clk_mmc: clk_disable_unprepare(host->clk_mmc); - clk_disable_unprepare(host->clk_ahb); + return ret; +} - dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); - mmc_free_host(mmc); +static int sunxi_mmc_runtime_suspend(struct device *dev) +{ + struct mmc_host *mmc = dev_get_drvdata(dev); + struct sunxi_mmc_host *host = mmc_priv(mmc); + + clk_disable_unprepare(host->clk_sample); + clk_disable_unprepare(host->clk_output); + clk_disable_unprepare(host->clk_mmc); return 0; } +static const struct dev_pm_ops sunxi_mmc_pm_ops = { + SET_RUNTIME_PM_OPS(sunxi_mmc_runtime_suspend, + sunxi_mmc_runtime_resume, + NULL) +}; + static struct platform_driver sunxi_mmc_driver = { .driver = { .name = "sunxi-mmc", .of_match_table = of_match_ptr(sunxi_mmc_of_match), + .pm = &sunxi_mmc_pm_ops, }, .probe = sunxi_mmc_probe, .remove = sunxi_mmc_remove,