From patchwork Mon Sep 20 18:11:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 12507121 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 96CFAC433F5 for ; Tue, 21 Sep 2021 02:45:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7BEC161211 for ; Tue, 21 Sep 2021 02:45:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352560AbhIUCqm (ORCPT ); Mon, 20 Sep 2021 22:46:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35722 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241609AbhIUCDF (ORCPT ); Mon, 20 Sep 2021 22:03:05 -0400 Received: from mail-lf1-x12c.google.com (mail-lf1-x12c.google.com [IPv6:2a00:1450:4864:20::12c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4434CC14091B; Mon, 20 Sep 2021 11:12:24 -0700 (PDT) Received: by mail-lf1-x12c.google.com with SMTP id u8so19850027lff.9; Mon, 20 Sep 2021 11:12:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bHhQzalkL4HJ+6Pj2vchyrjPmLkUiKGrqSO4eo7D4QI=; b=QX2xNvQxTCFlcCP6Bb7nyEQFApx252nqY8XkhXt5afJ7eILF0NjCF5276aoYGDyN/X CoDF9iuNmMvhBtq7X3z7G5x7uGmdkkdae1Osq34IMXvihfWpEsdJ6dsR3EVMYEuC4d21 AMXfB+7Ir5NUcPdRcWelpzJi6rcKBGnUwoQW4zBRpDwUmiRoVbpxdoHxd9rx1vd1BRgJ xeDw6QiJE0XZjZcRHYa6y5PO0lUG5N0F2HdMeePLVwtu9Tdb+JOWLrI4UbGzur9p5L4S 6/TqbIIxoSz/qzUOR79UswnauYFph5CtUoojh3/I4bbQJGoejmV9p009PJhMR10BpcQ4 1U6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bHhQzalkL4HJ+6Pj2vchyrjPmLkUiKGrqSO4eo7D4QI=; b=567BZ/HC71HwvgD9VJA7kXP6+pKtLVAI8G1cKzy+u6h06b/qptREINAiby3KcL/hNQ PTpdGR1tQaroIteE7c9rUoYRQwNcevfIxq3xwbqHwtxXjs4c9cx/IOwpt+LWWWdRItMU uBgSh3MdVRhD5ZZ2Lg6JlVvr6hNW+UMxFAdFhDPbBhcAjDIgqVEpCOTt8dNrEioSzIdu IXdXrRWnJEU0afgrDEY7lCHtG3vTESuocnN9FhPq0DD2jw/cr4L8ylIDTC7UeXDpPDyM arpVVolycYsOLoSR89j26Efk5JvyzPpEK2Hoj+TXe0gnTu6YXkuNNJhw2mp2TlMr2onV 8eKw== X-Gm-Message-State: AOAM532O9rF6x5BWrMVZAwvO5ru2vlBlAdgBF2v0v7LGf/3Ok+0+cOLq cfSAvqs3iNvj9ogv066IsKo= X-Google-Smtp-Source: ABdhPJxl8ZXALhmfr8D/lOOzfy/DiAFlumABJ3V1PTBrwbfqBGWBRN8X326HimyKQrX9JgL1vOVkPA== X-Received: by 2002:ac2:484e:: with SMTP id 14mr21015703lfy.140.1632161543269; Mon, 20 Sep 2021 11:12:23 -0700 (PDT) Received: from localhost.localdomain (46-138-151-206.dynamic.spd-mgts.ru. [46.138.151.206]) by smtp.gmail.com with ESMTPSA id u3sm1775677lju.107.2021.09.20.11.12.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 Sep 2021 11:12:23 -0700 (PDT) From: Dmitry Osipenko To: Thierry Reding , Jonathan Hunter , Ulf Hansson , Viresh Kumar , Stephen Boyd , Peter De Schrijver , Mikko Perttunen , Peter Chen , Lee Jones , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Nishanth Menon , Adrian Hunter , Rob Herring , Michael Turquette Cc: linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-staging@lists.linux.dev, linux-pwm@vger.kernel.org, linux-mmc@vger.kernel.org, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Mark Brown , Vignesh Raghavendra , Richard Weinberger , Miquel Raynal , Lucas Stach , Stefan Agner , Mauro Carvalho Chehab , David Heidelberg Subject: [PATCH v12 19/35] mmc: sdhci-tegra: Add runtime PM and OPP support Date: Mon, 20 Sep 2021 21:11:29 +0300 Message-Id: <20210920181145.19543-20-digetx@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210920181145.19543-1-digetx@gmail.com> References: <20210920181145.19543-1-digetx@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org The SDHCI on Tegra belongs to the core power domain and we're going to enable GENPD support for the core domain. Now SDHCI must be resumed using runtime PM API in order to initialize the SDHCI power state. The SDHCI clock rate must be changed using OPP API that will reconfigure the power domain performance state in accordance to the rate. Add runtime PM and OPP support to the SDHCI driver. Signed-off-by: Dmitry Osipenko --- drivers/mmc/host/sdhci-tegra.c | 80 +++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 16 deletions(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index a5001875876b..71955150dc43 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -24,6 +26,8 @@ #include #include +#include + #include "sdhci-pltfm.h" #include "cqhci.h" @@ -760,7 +764,9 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); + struct device *dev = mmc_dev(host->mmc); unsigned long host_clk; + int err; if (!clock) return sdhci_set_clock(host, clock); @@ -778,7 +784,12 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) * from clk_get_rate() is used. */ host_clk = tegra_host->ddr_signaling ? clock * 2 : clock; - clk_set_rate(pltfm_host->clk, host_clk); + + err = dev_pm_opp_set_rate(dev, host_clk); + if (err) + dev_err(dev, "failed to set clk rate to %luHz: %d\n", + host_clk, err); + tegra_host->curr_clk_rate = host_clk; if (tegra_host->ddr_signaling) host->max_clk = host_clk; @@ -1705,7 +1716,6 @@ static int sdhci_tegra_probe(struct platform_device *pdev) "failed to get clock\n"); goto err_clk_get; } - clk_prepare_enable(clk); pltfm_host->clk = clk; tegra_host->rst = devm_reset_control_get_exclusive(&pdev->dev, @@ -1716,15 +1726,25 @@ static int sdhci_tegra_probe(struct platform_device *pdev) goto err_rst_get; } + pm_runtime_enable(&pdev->dev); + + rc = devm_tegra_core_dev_init_opp_table_common(&pdev->dev); + if (rc) + goto err_pm_get; + + rc = pm_runtime_resume_and_get(&pdev->dev); + if (rc) + goto err_pm_get; + rc = reset_control_assert(tegra_host->rst); if (rc) - goto err_rst_get; + goto err_rst_assert; usleep_range(2000, 4000); rc = reset_control_deassert(tegra_host->rst); if (rc) - goto err_rst_get; + goto err_rst_assert; usleep_range(2000, 4000); @@ -1736,8 +1756,11 @@ static int sdhci_tegra_probe(struct platform_device *pdev) err_add_host: reset_control_assert(tegra_host->rst); +err_rst_assert: + pm_runtime_put(&pdev->dev); +err_pm_get: + pm_runtime_disable(&pdev->dev); err_rst_get: - clk_disable_unprepare(pltfm_host->clk); err_clk_get: clk_disable_unprepare(tegra_host->tmclk); err_power_req: @@ -1756,19 +1779,37 @@ static int sdhci_tegra_remove(struct platform_device *pdev) reset_control_assert(tegra_host->rst); usleep_range(2000, 4000); - clk_disable_unprepare(pltfm_host->clk); - clk_disable_unprepare(tegra_host->tmclk); + pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + clk_disable_unprepare(tegra_host->tmclk); sdhci_pltfm_free(pdev); return 0; } -#ifdef CONFIG_PM_SLEEP -static int __maybe_unused sdhci_tegra_suspend(struct device *dev) +static int __maybe_unused sdhci_tegra_runtime_suspend(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + clk_disable_unprepare(pltfm_host->clk); + + return 0; +} + +static int __maybe_unused sdhci_tegra_runtime_resume(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + return clk_prepare_enable(pltfm_host->clk); +} + +static int __maybe_unused sdhci_tegra_suspend(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); int ret; if (host->mmc->caps2 & MMC_CAP2_CQE) { @@ -1783,17 +1824,22 @@ static int __maybe_unused sdhci_tegra_suspend(struct device *dev) return ret; } - clk_disable_unprepare(pltfm_host->clk); + ret = pm_runtime_force_suspend(dev); + if (ret) { + sdhci_resume_host(host); + cqhci_resume(host->mmc); + return ret; + } + return 0; } static int __maybe_unused sdhci_tegra_resume(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); int ret; - ret = clk_prepare_enable(pltfm_host->clk); + ret = pm_runtime_force_resume(dev); if (ret) return ret; @@ -1812,13 +1858,15 @@ static int __maybe_unused sdhci_tegra_resume(struct device *dev) suspend_host: sdhci_suspend_host(host); disable_clk: - clk_disable_unprepare(pltfm_host->clk); + pm_runtime_force_suspend(dev); return ret; } -#endif -static SIMPLE_DEV_PM_OPS(sdhci_tegra_dev_pm_ops, sdhci_tegra_suspend, - sdhci_tegra_resume); +static const struct dev_pm_ops sdhci_tegra_dev_pm_ops = { + SET_RUNTIME_PM_OPS(sdhci_tegra_runtime_suspend, sdhci_tegra_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(sdhci_tegra_suspend, sdhci_tegra_resume) +}; static struct platform_driver sdhci_tegra_driver = { .driver = {