From patchwork Sat Jul 10 01:32:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 472322 Delivered-To: patch@linaro.org Received: by 2002:a02:c94a:0:0:0:0:0 with SMTP id u10csp822109jao; Fri, 9 Jul 2021 18:33:22 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwq9gTPh21HLN3THyyqra9jbwgFZ+SbdApZCqfHAotWgmdNr/Fvs2SZ2igqHFmJieViqJBT X-Received: by 2002:a17:906:1299:: with SMTP id k25mr40233054ejb.139.1625880802363; Fri, 09 Jul 2021 18:33:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1625880802; cv=none; d=google.com; s=arc-20160816; b=HU9ugB6akv2uIHtbtS4DY4TWXH/jMRuh4oZOJVLlAdUOx6n+DSikdSmBi9b3gpeJr0 6tNMSXNW6XJwdYn9Wy1ykWewjmxPbsX0808XjfUrOkBbTV18gTSOHhv1qtRQPe1YKY5o 6v6YWgmFTGenut0M8DavvF3Bbmhu7wnJOQoIGtowAu9FtJs2bQ5VjlZ/Zu6qTYS3P4BV o4CJfuETAa7HqmCaKQBXttdWxxc6M8FySkCikYJU93+vUYkSeV54Cr5Ejd5jzsRmUlEX Ta7KPCxbxH5h0X0nPoJaOiTtXM2pu9CQ8AzfsgcIC2WD7RF/3LeGs7mnDzTXepyFsJco v9Kw== 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=MmT4w4hHtpG6udw9hhwkauK+X8W9kJHpM/x3jD7TEA8=; b=iOSEZXNeug/4jckjiiOuA5S8Z5/j8Q09IzGJ+aNusR63bmUCaCbtYLR6JXrBDc/Q52 4U8OBU3ALyIFgCFB+iQD1Jh+Y+shHvvAAETHyUEnaqI/Lfh8G2ZBD4AUM05yCvpxXmRq 5KlB8woUrrMA+a6oFQYPvRQu+mWLa6rFbi4o0YXx176vcuDCs+MNWa78vSwW1LAywKqy lVznDmTPGTG64c0S122fp8LWt7Zo/2A9kAKmPPd+ToJQNlf0MW/0appV2tSZ1tTjhmOz 7RYdsI14R767qVB3C8MZ/1iPLgruIAKccemctP/YWIX9bovfTyI1KbLOccDYfO8P/n1F aQ9g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=k69IQFdO; spf=pass (google.com: domain of devicetree-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id dz14si9450283edb.241.2021.07.09.18.33.22; Fri, 09 Jul 2021 18:33:22 -0700 (PDT) Received-SPF: pass (google.com: domain of devicetree-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=@linaro.org header.s=google header.b=k69IQFdO; spf=pass (google.com: domain of devicetree-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231782AbhGJBfu (ORCPT + 7 others); Fri, 9 Jul 2021 21:35:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39344 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231682AbhGJBfo (ORCPT ); Fri, 9 Jul 2021 21:35:44 -0400 Received: from mail-lj1-x229.google.com (mail-lj1-x229.google.com [IPv6:2a00:1450:4864:20::229]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 50E38C061788 for ; Fri, 9 Jul 2021 18:32:59 -0700 (PDT) Received: by mail-lj1-x229.google.com with SMTP id u25so10913556ljj.11 for ; Fri, 09 Jul 2021 18:32:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MmT4w4hHtpG6udw9hhwkauK+X8W9kJHpM/x3jD7TEA8=; b=k69IQFdOOpbNxtccX8zGgd7k39UhsGuZYDVjxirpPCIVpo053A0jBc4pkWmVft53oP Cpd8scHhkJANM77hwUA/kjnNaLssJUQmRcSBTWsy3udqDs37mbAAou4dWS3hQzrpnAEK +0dNNUbNaHKJ3MfeMYWNhVRIDWJPVH4JjfVvD/+QPwIuggJQ+gHGTivw3lziRtvDTOtT Is/85tPOCiBhE/4FA83+arNl29FAyqQR2TtVuaochJTLbgG5a5fOStASDqpPDlpZjg4y AbfYktgvepROgVI6uKJqKIQQ+dNFN7HvAx8esOsezzghm137goqNM6G3LIzSvdl8CE/E mgqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MmT4w4hHtpG6udw9hhwkauK+X8W9kJHpM/x3jD7TEA8=; b=GF30fy4MpbdIbjt++oVeIznhavF/5LQrtLmtzzkdipqrVqnXe2c4F/5zyH7PnEB9tI EN9Cxnlejak8RP46YGOew4i4wVDElo8xuJ8vmelvK+AEGZbEh0BqURQQtV0LsPnpWBLU uWdBp3l3gRZxpOHvkO/qH0kzt3PNlh7kiR1tAV6byVY2aeWPe9LX6bQD1VTRGzBYSTee U81L246tZyPcOUSdtZ56t4t8uRJvXKxFQ6KqK2gL7bWI3OZWfD1k49P+U0NIESWGAPbt 3zk7vmvLG/n6XXDBtjWxh731SHGTGTrmVaKbJrGaG0EbZ65Km4ySQlOg9r27YdEK34eO m6Mg== X-Gm-Message-State: AOAM532gGwZABuSeDIVz/Q8ek4+kkjmqReoknpuH4i92pcl2khZZdegj 9mB4zP2SSiAtANSeLhuSmmVK0Q== X-Received: by 2002:a2e:7801:: with SMTP id t1mr31376168ljc.330.1625880777625; Fri, 09 Jul 2021 18:32:57 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id p13sm588788lfh.206.2021.07.09.18.32.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 09 Jul 2021 18:32:57 -0700 (PDT) From: Dmitry Baryshkov To: Andy Gross , Bjorn Andersson , Rob Herring , Stephen Boyd , Taniya Das , Jonathan Marek , Michael Turquette Cc: linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, Bryan O'Donoghue , Mark Brown , Ulf Hansson , linux-kernel@vger.kernel.org Subject: [PATCH v4 3/6] clk: qcom: gdsc: enable optional power domain support Date: Sat, 10 Jul 2021 04:32:50 +0300 Message-Id: <20210710013253.1134341-4-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210710013253.1134341-1-dmitry.baryshkov@linaro.org> References: <20210710013253.1134341-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org On sm8250 dispcc and videocc registers are powered up by the MMCX power domain. Currently we use a regulator to enable this domain on demand, however this has some consequences, as genpd code is not reentrant. Teach Qualcomm clock controller code about setting up runtime PM and using specified genpd for gdsc powerup. Clock core will use runtime_pm calls to ensure that clock registers are accessible. The genpd code will powerup the parent domain when gdsc is powered, thus ensuring that the power stays on. Make gdsc code also use pm_runtime calls to ensure that registers are accessible during the gdsc_enable/gdsc_disable operations. Signed-off-by: Dmitry Baryshkov --- drivers/clk/qcom/common.c | 37 +++++++++++++++++---- drivers/clk/qcom/gdsc.c | 67 +++++++++++++++++++++++++++++++++++++-- drivers/clk/qcom/gdsc.h | 2 ++ 3 files changed, 97 insertions(+), 9 deletions(-) -- 2.30.2 diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 60d2a78d1395..43d8f8feeb3c 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "common.h" #include "clk-rcg.h" @@ -224,6 +225,11 @@ static struct clk_hw *qcom_cc_clk_hw_get(struct of_phandle_args *clkspec, return cc->rclks[idx] ? &cc->rclks[idx]->hw : NULL; } +static void qcom_cc_pm_runtime_disable(void *data) +{ + pm_runtime_disable(data); +} + int qcom_cc_really_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc, struct regmap *regmap) { @@ -241,6 +247,18 @@ int qcom_cc_really_probe(struct platform_device *pdev, if (!cc) return -ENOMEM; + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put(dev); + pm_runtime_disable(dev); + return ret; + } + + ret = devm_add_action_or_reset(dev, qcom_cc_pm_runtime_disable, dev); + if (ret) + goto err; + reset = &cc->reset; reset->rcdev.of_node = dev->of_node; reset->rcdev.ops = &qcom_reset_ops; @@ -251,7 +269,7 @@ int qcom_cc_really_probe(struct platform_device *pdev, ret = devm_reset_controller_register(dev, &reset->rcdev); if (ret) - return ret; + goto err; if (desc->gdscs && desc->num_gdscs) { scd = devm_kzalloc(dev, sizeof(*scd), GFP_KERNEL); @@ -262,11 +280,11 @@ int qcom_cc_really_probe(struct platform_device *pdev, scd->num = desc->num_gdscs; ret = gdsc_register(scd, &reset->rcdev, regmap); if (ret) - return ret; + goto err; ret = devm_add_action_or_reset(dev, qcom_cc_gdsc_unregister, scd); if (ret) - return ret; + goto err; } cc->rclks = rclks; @@ -277,7 +295,7 @@ int qcom_cc_really_probe(struct platform_device *pdev, for (i = 0; i < num_clk_hws; i++) { ret = devm_clk_hw_register(dev, clk_hws[i]); if (ret) - return ret; + goto err; } for (i = 0; i < num_clks; i++) { @@ -286,14 +304,21 @@ int qcom_cc_really_probe(struct platform_device *pdev, ret = devm_clk_register_regmap(dev, rclks[i]); if (ret) - return ret; + goto err; } ret = devm_of_clk_add_hw_provider(dev, qcom_cc_clk_hw_get, cc); if (ret) - return ret; + goto err; + + pm_runtime_put(dev); return 0; + +err: + pm_runtime_put(dev); + + return ret; } EXPORT_SYMBOL_GPL(qcom_cc_really_probe); diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index 51ed640e527b..cfe875f87efe 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,30 @@ enum gdsc_status { GDSC_ON }; +static int gdsc_pm_runtime_get(struct gdsc *sc) +{ + int ret; + + if (!sc->dev) + return 0; + + ret = pm_runtime_get_sync(sc->dev); + if (ret < 0) { + pm_runtime_put_noidle(sc->dev); + return ret; + } + + return 0; +} + +static int gdsc_pm_runtime_put(struct gdsc *sc) +{ + if (!sc->dev) + return 0; + + return pm_runtime_put_sync(sc->dev); +} + /* Returns 1 if GDSC status is status, 0 if not, and < 0 on error */ static int gdsc_check_status(struct gdsc *sc, enum gdsc_status status) { @@ -232,9 +257,8 @@ static void gdsc_retain_ff_on(struct gdsc *sc) regmap_update_bits(sc->regmap, sc->gdscr, mask, mask); } -static int gdsc_enable(struct generic_pm_domain *domain) +static int _gdsc_enable(struct gdsc *sc) { - struct gdsc *sc = domain_to_gdsc(domain); int ret; if (sc->pwrsts == PWRSTS_ON) @@ -290,11 +314,26 @@ static int gdsc_enable(struct generic_pm_domain *domain) return 0; } -static int gdsc_disable(struct generic_pm_domain *domain) +static int gdsc_enable(struct generic_pm_domain *domain) { struct gdsc *sc = domain_to_gdsc(domain); int ret; + ret = gdsc_pm_runtime_get(sc); + if (ret) + return ret; + + ret = _gdsc_enable(sc); + + gdsc_pm_runtime_put(sc); + + return ret; +} + +static int _gdsc_disable(struct gdsc *sc) +{ + int ret; + if (sc->pwrsts == PWRSTS_ON) return gdsc_assert_reset(sc); @@ -329,6 +368,22 @@ static int gdsc_disable(struct generic_pm_domain *domain) return 0; } +static int gdsc_disable(struct generic_pm_domain *domain) +{ + struct gdsc *sc = domain_to_gdsc(domain); + int ret; + + ret = gdsc_pm_runtime_get(sc); + if (ret) + return ret; + + ret = _gdsc_disable(sc); + + gdsc_pm_runtime_put(sc); + + return ret; +} + static int gdsc_init(struct gdsc *sc) { u32 mask, val; @@ -425,6 +480,8 @@ int gdsc_register(struct gdsc_desc *desc, for (i = 0; i < num; i++) { if (!scs[i]) continue; + if (pm_runtime_enabled(dev)) + scs[i]->dev = dev; scs[i]->regmap = regmap; scs[i]->rcdev = rcdev; ret = gdsc_init(scs[i]); @@ -439,6 +496,8 @@ int gdsc_register(struct gdsc_desc *desc, continue; if (scs[i]->parent) pm_genpd_add_subdomain(scs[i]->parent, &scs[i]->pd); + else if (!IS_ERR_OR_NULL(dev->pm_domain)) + pm_genpd_add_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd); } return of_genpd_add_provider_onecell(dev->of_node, data); @@ -457,6 +516,8 @@ void gdsc_unregister(struct gdsc_desc *desc) continue; if (scs[i]->parent) pm_genpd_remove_subdomain(scs[i]->parent, &scs[i]->pd); + else if (!IS_ERR_OR_NULL(dev->pm_domain)) + pm_genpd_remove_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd); } of_genpd_del_provider(dev->of_node); } diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h index 5bb396b344d1..702d47a87af6 100644 --- a/drivers/clk/qcom/gdsc.h +++ b/drivers/clk/qcom/gdsc.h @@ -25,6 +25,7 @@ struct reset_controller_dev; * @resets: ids of resets associated with this gdsc * @reset_count: number of @resets * @rcdev: reset controller + * @dev: the device holding the GDSC, used for pm_runtime calls */ struct gdsc { struct generic_pm_domain pd; @@ -58,6 +59,7 @@ struct gdsc { const char *supply; struct regulator *rsupply; + struct device *dev; }; struct gdsc_desc {