Received: by 2002:a05:6a11:4021:0:0:0:0 with SMTP id ky33csp3444589pxb; Sun, 26 Sep 2021 15:45:08 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy7I2RWzaSnIJXOsVcY+Rvz+A43hWTkRdwzT03CIc09lMl4UiRz2wgxJeZkk0YxfakUcHBx X-Received: by 2002:a17:90a:1a19:: with SMTP id 25mr16038680pjk.34.1632696308547; Sun, 26 Sep 2021 15:45:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1632696308; cv=none; d=google.com; s=arc-20160816; b=oBnMbZUJtBefKoJSC+snc6DsIM7J9ml04NNFZafJQIjc70gHBeOYlprcZU5a/KBC+P A6toUWMnuVn5Srag002DewY9aOGBB98KeP77Z5n9exJo9afIeqfAtKaWdYPbXYJZ1Muc wU7BfxkoiZsGAYRGy4+m5w/8f9ZOTrnGidkFIYs678vreiP44x5PbnzzPcvJYnYfvmgY xBXi7NnoU25LDqyozfO3eLSNdCY2Fjw9uspULlIXspyYpN8le16/I5iV0h/CdwCVVPxT D+FAFKCUkW67F8CvniWlhT9OjAmTPlVw4mot4OeKoQoG3Db3AkoJyiv3ZzTqbe43eN0S fefw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=TplqdteIbqpMA+cRsM4zt2txSdRrivaAa9SZu7q2V5k=; b=ZrIxmjPz6dCwGiM4z0uXweh8DgRkejVT+Kq3XiU+3aJ/Toi2/ob0AmFqBkqMoVTEUT uRoczl8uvlzevt3lvYmhhouwIriVTlMvpPVUAz0FOZk9yJKl6Sf95Cw4w4AAsF1bZcE0 hm4s5A/m4tAr67y4XOBl5zhKZbr1W89jbz7/U5mx+t2hRvtVbcsDIBSkT3dhvOtk37bg hsMBikULEuDJI1GuAiz0ui7lysSF5cdqh4syB2QGUY1OYETG9h+6fdsLK3DtaPsAON/W c60lykQKT2jxVmujqezbcG1mjpCpLBUTJHpPxbjkGh/WRvj9vuN34m941Vtifxuipkx2 +mLA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=DT8SqkTx; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w16si19836763plk.198.2021.09.26.15.44.56; Sun, 26 Sep 2021 15:45:08 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=DT8SqkTx; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232622AbhIZWp1 (ORCPT + 99 others); Sun, 26 Sep 2021 18:45:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43406 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232037AbhIZWoZ (ORCPT ); Sun, 26 Sep 2021 18:44:25 -0400 Received: from mail-lf1-x136.google.com (mail-lf1-x136.google.com [IPv6:2a00:1450:4864:20::136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B475BC06176F; Sun, 26 Sep 2021 15:42:48 -0700 (PDT) Received: by mail-lf1-x136.google.com with SMTP id b20so68764452lfv.3; Sun, 26 Sep 2021 15:42:48 -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=TplqdteIbqpMA+cRsM4zt2txSdRrivaAa9SZu7q2V5k=; b=DT8SqkTx9xz6k5lBqurvLVNFLdDdNs18xHEmnjZRBgAU1JSad+bgMJ81V3A4GmsmTZ XowmCira9qNyl8dSJVMy/CQy5BcPRZhPsuaAFiu1jL+qX/a5eYq2O+sQc7xSfauFkP4m +pn2x9DI/qGMzxHWuTKSB+M18jvc1+XJaBhC0YuMgopcrO0gn/8p6tvkSyfDLx93MaOx qYRNA8NToNmautjcGGBRmv4GKJFBj6OsUDIAu7dXCDn704AXf/iCp0Sr82+qnR3FufLx PrZkoA1pl/W18qvaRpoqzCfJZzgnN2nvFdueq1mSh2rjjCQLbwpO0RJnPPH2g2WgZ0Hm IHkg== 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=TplqdteIbqpMA+cRsM4zt2txSdRrivaAa9SZu7q2V5k=; b=pZL85+yNuPvOmJuuPjjQ7Vx9+BNWwRRwmmWpuSUUVYRpYnWLXwqz628dF9ZTr765xF hxY/9ZOegF65asTwGbbi62Yx5w+bjqOQ6a0NYq3N1YgpAMpGbB3vGHf58bmyf/i5UR7g 2s7GgpeGKpkLJ932zzpxgskUR34nS0oaW7bFNSCqkA/8hNve5jNuRC97s++WWJA9gbrh WKqz2dV8rncg2RG23Q57a+Cpp9MoZBuFRMMoTBDeKELN+c3mbVzU3RFXdilPktWCH/Wa rNWoFGqOpizHOqTcZlX3MOrWNS38gbFrJvOtsYaUgSNkgf9FiwlBaTNB8rIpA0ZcPhQB 2QnQ== X-Gm-Message-State: AOAM533LZ6V0iX/iN1R2ECy3TDx0URL2JmLUXP149I0Ve48Bc8Nh6nrp 92oEmFnSwsi6w696JxFmdxFby46nKiE= X-Received: by 2002:a05:6512:750:: with SMTP id c16mr21689714lfs.21.1632696167148; Sun, 26 Sep 2021 15:42:47 -0700 (PDT) Received: from localhost.localdomain (46-138-80-108.dynamic.spd-mgts.ru. [46.138.80.108]) by smtp.gmail.com with ESMTPSA id m10sm1408899lfr.272.2021.09.26.15.42.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Sep 2021 15:42:46 -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=20Kleine-K=C3=B6nig?= , Nishanth Menon , Adrian Hunter , 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 v13 18/35] pwm: tegra: Add runtime PM and OPP support Date: Mon, 27 Sep 2021 01:40:41 +0300 Message-Id: <20210926224058.1252-19-digetx@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210926224058.1252-1-digetx@gmail.com> References: <20210926224058.1252-1-digetx@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The PWM on Tegra belongs to the core power domain and we're going to enable GENPD support for the core domain. Now PWM must be resumed using runtime PM API in order to initialize the PWM power state. The PWM 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 PWM driver. Signed-off-by: Dmitry Osipenko --- drivers/pwm/pwm-tegra.c | 88 ++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 18 deletions(-) diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index 11a10b575ace..afb5ecde007e 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -42,12 +42,16 @@ #include #include #include +#include #include #include #include +#include #include #include +#include + #define PWM_ENABLE (1 << 31) #define PWM_DUTY_WIDTH 8 #define PWM_DUTY_SHIFT 16 @@ -145,7 +149,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, required_clk_rate = (NSEC_PER_SEC / period_ns) << PWM_DUTY_WIDTH; - err = clk_set_rate(pc->clk, required_clk_rate); + err = dev_pm_opp_set_rate(pc->dev, required_clk_rate); if (err < 0) return -EINVAL; @@ -181,8 +185,8 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, * before writing the register. Otherwise, keep it enabled. */ if (!pwm_is_enabled(pwm)) { - err = clk_prepare_enable(pc->clk); - if (err < 0) + err = pm_runtime_resume_and_get(pc->dev); + if (err) return err; } else val |= PWM_ENABLE; @@ -193,7 +197,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, * If the PWM is not enabled, turn the clock off again to save power. */ if (!pwm_is_enabled(pwm)) - clk_disable_unprepare(pc->clk); + pm_runtime_put(pc->dev); return 0; } @@ -204,8 +208,8 @@ static int tegra_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) int rc = 0; u32 val; - rc = clk_prepare_enable(pc->clk); - if (rc < 0) + rc = pm_runtime_resume_and_get(pc->dev); + if (rc) return rc; val = pwm_readl(pc, pwm->hwpwm); @@ -224,7 +228,7 @@ static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) val &= ~PWM_ENABLE; pwm_writel(pc, pwm->hwpwm, val); - clk_disable_unprepare(pc->clk); + pm_runtime_put_sync(pc->dev); } static const struct pwm_ops tegra_pwm_ops = { @@ -256,11 +260,23 @@ static int tegra_pwm_probe(struct platform_device *pdev) if (IS_ERR(pwm->clk)) return PTR_ERR(pwm->clk); + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret = devm_tegra_core_dev_init_opp_table_common(&pdev->dev); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; + /* Set maximum frequency of the IP */ - ret = clk_set_rate(pwm->clk, pwm->soc->max_frequency); + ret = dev_pm_opp_set_rate(pwm->dev, pwm->soc->max_frequency); if (ret < 0) { dev_err(&pdev->dev, "Failed to set max frequency: %d\n", ret); - return ret; + goto put_pm; } /* @@ -278,7 +294,7 @@ static int tegra_pwm_probe(struct platform_device *pdev) if (IS_ERR(pwm->rst)) { ret = PTR_ERR(pwm->rst); dev_err(&pdev->dev, "Reset control is not found: %d\n", ret); - return ret; + goto put_pm; } reset_control_deassert(pwm->rst); @@ -291,34 +307,67 @@ static int tegra_pwm_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); reset_control_assert(pwm->rst); - return ret; + goto put_pm; } + pm_runtime_put(&pdev->dev); + return 0; +put_pm: + pm_runtime_put(&pdev->dev); + return ret; } static int tegra_pwm_remove(struct platform_device *pdev) { struct tegra_pwm_chip *pc = platform_get_drvdata(pdev); + int err; pwmchip_remove(&pc->chip); + err = pm_runtime_resume_and_get(pc->dev); + if (err) + return err; + reset_control_assert(pc->rst); + pm_runtime_put(pc->dev); return 0; } -#ifdef CONFIG_PM_SLEEP -static int tegra_pwm_suspend(struct device *dev) +static int __maybe_unused tegra_pwm_runtime_suspend(struct device *dev) { - return pinctrl_pm_select_sleep_state(dev); + struct tegra_pwm_chip *pc = dev_get_drvdata(dev); + int err; + + clk_disable_unprepare(pc->clk); + + err = pinctrl_pm_select_sleep_state(dev); + if (err) { + clk_prepare_enable(pc->clk); + return err; + } + + return 0; } -static int tegra_pwm_resume(struct device *dev) +static int __maybe_unused tegra_pwm_runtime_resume(struct device *dev) { - return pinctrl_pm_select_default_state(dev); + struct tegra_pwm_chip *pc = dev_get_drvdata(dev); + int err; + + err = pinctrl_pm_select_default_state(dev); + if (err) + return err; + + err = clk_prepare_enable(pc->clk); + if (err) { + pinctrl_pm_select_sleep_state(dev); + return err; + } + + return 0; } -#endif static const struct tegra_pwm_soc tegra20_pwm_soc = { .num_channels = 4, @@ -344,7 +393,10 @@ static const struct of_device_id tegra_pwm_of_match[] = { MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); static const struct dev_pm_ops tegra_pwm_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(tegra_pwm_suspend, tegra_pwm_resume) + SET_RUNTIME_PM_OPS(tegra_pwm_runtime_suspend, tegra_pwm_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; static struct platform_driver tegra_pwm_driver = { -- 2.32.0