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: 122454 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp5402853qgn; Wed, 20 Dec 2017 02:50:55 -0800 (PST) X-Google-Smtp-Source: ACJfBou+Ei5fa/2R2qsbC9DYNp0+tCbVeUKvJxt/NcmmhzWiEh6eJqz8b/yKU6wvGka0ANyiOeyj X-Received: by 10.99.101.7 with SMTP id z7mr5816119pgb.253.1513767055430; Wed, 20 Dec 2017 02:50:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1513767055; cv=none; d=google.com; s=arc-20160816; b=uWUGor3j2BuqG8HeI3ohwhMqgOfEqA0tgGzeST6zOilOcFKO+5T7Q7UusYJDdul4lE 40SyMgPgujrrwSX9P97tERBn2sqeHAISdI2moevek6fxP1BhzpIQ5CPPM5Zw3bHhw7eg M0rGVSQonQExaLYbbNpsXwbwUCosfjEQMyFJT/S6Hn2MBq+t8+/GkL0vaqJQMoGqk2VT 2GforbjCgcR7F2AI2pntMLoBsI1CEs00zLHdrUptCkkbPWZi8hke3mxpiK93BmtePOy2 /HG8wOrS43D8S+dQfXHTGm7iiV6QcNPAf47wVGWTiBwAGYyuLyYeTmZqMS5LfmhlL1mr dlQw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=/YabBMk6S8EIxMSLLyRt69v/HMBFDrtyHCNvCJSdKR0=; b=U94rMIPaMrXsGxf15IvB7+z0PPv8N+r91uvL6hjdrvziHLXx2Z+fRuwwVNCHzYcpPx GBmhVJXYWpkOGidhhGd9Qe8LMrjqtzvRp8SzXA22O4MFGj9vbWWhBPP84ctLPVZh0TmP oA0r3lIfpQBzigxeHYeC9YF6pLylbnaldo2Ovyjc2eF7xuPeb2NcCUM3+j08JHNxz3ah bAhDiMdy3zajY/pWry4JpaoMKEQSMDsExyswmVHAJLg/GmA0xRk7+l1geQVGNExDqTin M5YE04AVgf/hbV4WAEyIVHj/EhO/ryPiE8gAPp9WxbA5OSyhK6Cw76MQQxUpWVAEO0VX laow== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-mmc-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-mmc-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w31si12482718pla.517.2017.12.20.02.50.55; Wed, 20 Dec 2017 02:50:55 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-mmc-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-mmc-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-mmc-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753629AbdLTKuy (ORCPT + 6 others); Wed, 20 Dec 2017 05:50:54 -0500 Received: from mail.free-electrons.com ([62.4.15.54]:54100 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753283AbdLTKux (ORCPT ); Wed, 20 Dec 2017 05:50:53 -0500 Received: by mail.free-electrons.com (Postfix, from userid 110) id 5A0B820949; Wed, 20 Dec 2017 11:50:51 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 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 Cc: linux-arm-kernel@lists.infradead.org, linux-mmc@vger.kernel.org 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: Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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(-) -- git-series 0.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html 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,