From patchwork Tue Jul 11 18:20:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 9835377 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 AC03F602A0 for ; Tue, 11 Jul 2017 18:20:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A181328567 for ; Tue, 11 Jul 2017 18:20:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 961422856B; Tue, 11 Jul 2017 18:20:28 +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.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1398428567 for ; Tue, 11 Jul 2017 18:20:28 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DA1946E1D2; Tue, 11 Jul 2017 18:20:26 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qt0-x242.google.com (mail-qt0-x242.google.com [IPv6:2607:f8b0:400d:c0d::242]) by gabe.freedesktop.org (Postfix) with ESMTPS id C439F6E1D2 for ; Tue, 11 Jul 2017 18:20:24 +0000 (UTC) Received: by mail-qt0-x242.google.com with SMTP id c20so36560qte.0 for ; Tue, 11 Jul 2017 11:20:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=54Hym7gq4zyBKwBDlTGWGP+nAnI7mggUJS2Z5nvYXRI=; b=OFcMRWEUwkeDgUYUCqBUG7l66oDGmL8BXsZmeykOoEIx8z/skvsyhsLhwmrGoUcAUA Ewt3JEEs+ijlZE5U0KvfoJIbJ5s2Asxx7TPGHg76dGBoM6KNqpRp+PtYa5z7dPubBJjW pQp7iOz00y8Xm9Bf0msFebAKbuJgCq0zF4Jm+QlUaCAssWJdhEDePGf87L8L12b4XIA/ LqYg48emygIDqmfnvIUxATIJSEitJ7buXvoeI1g679RaVDJRSOvp4D6bPcFrlrx6noP2 sAkb3vo7xh44YEtdCV9D+jaF5FEE02erEirndK1+2P23obDr7hIboIJHIGab7DMk/2sG tNdQ== 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; bh=54Hym7gq4zyBKwBDlTGWGP+nAnI7mggUJS2Z5nvYXRI=; b=Q+K3tIhU8zMrqGsWB+qQviJNqm8Ggicvdlh6U9fuLYJgwUsf8RIbS6RlrRhT74BdkD ntz2y1N3LqtXefnrhJsXfb6pmAiT7gNhZbXxVN3kW8D+dkrXMzZEb95wPRlqQcm4DqaL /t86ZMtZ95ISpw/lXz31/+Bnb6RXmX49mwbC0Rb3YnX4Rgn5bZ5IqT0f94TWA1aNk1Wz sA4vJWJyMgRvHTNvKG5JfceBq+EdYIszRUdl6YCP+OE1z+QH25pzDkGm7HsAZ4ST+DVd YXRZCWsbfygw/+1ZjfdjtrHoY6Mju8r+WD5tfEyQPhK4mZBvP+UhH8EYd8HTO+0lECBQ i+KA== X-Gm-Message-State: AIVw111tG1TExM3FKF+qym+XCA2v61ZCFI0uEyG0yt7F/7MuAfFDkMFP wOriOckdrUHV1URLlXQ= X-Received: by 10.237.60.212 with SMTP id e20mr1686714qtf.106.1499797223463; Tue, 11 Jul 2017 11:20:23 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id n21sm489511qkl.51.2017.07.11.11.20.21 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 11 Jul 2017 11:20:21 -0700 (PDT) From: Rob Clark To: dri-devel@lists.freedesktop.org, linux-clk@vger.kernel.org Subject: [RFC 1/3] clk: inherit display clocks enabled by bootloader Date: Tue, 11 Jul 2017 14:20:06 -0400 Message-Id: <20170711182008.28298-2-robdclark@gmail.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170711182008.28298-1-robdclark@gmail.com> References: <20170711182008.28298-1-robdclark@gmail.com> Cc: linux-arm-msm@vger.kernel.org, Michael Turquette , Stephen Boyd , viresh.kumar@linaro.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP The goal here is to support inheriting a display setup by bootloader, although there may also be some non-display related use-cases. Rough idea is to add a flag for clks and power domains that might already be enabled when kernel starts, and make corresponding fixups to clk enable/prepare_count and power-domain state so that these are not automatically disabled late in boot. If bootloader is enabling display, and kernel is using efifb before real display driver is loaded (potentially from kernel module after userspace starts, in a typical distro kernel), we don't want to kill the clocks and power domains that are used by the display before userspace starts. Second part is for drm/msm to check if display related clocks are enabled when it is loaded, and if so read back hw state to sync existing display state w/ software state, and skip the initial clk_enable's and otherwise fixing up clk/regulator/etc ref counts (skipping the normal display-enable codepaths), therefore inheriting the enable done by bootloader. Obviously this should be split up into multiple patches and many TODOs addressed. But I guess this is enough for now to start discussing the approach, and in particular how drm and clock/pd drivers work together to handle handover from bootloader. The CLK_INHERIT_BOOTLOADER and related gsdc flag should only be set on leaf nodes. --- drivers/clk/clk.c | 18 ++++++++++++++++++ drivers/clk/qcom/common.c | 28 ++++++++++++++++++++++++++++ drivers/clk/qcom/gcc-msm8916.c | 15 ++++++++------- drivers/clk/qcom/gdsc.c | 6 ++++++ drivers/clk/qcom/gdsc.h | 1 + include/linux/clk-provider.h | 1 + include/linux/clk.h | 9 +++++++++ 7 files changed, 71 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fc58c52a26b4..7c84e8d6e816 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -796,6 +796,24 @@ static void clk_disable_unused_subtree(struct clk_core *core) clk_core_disable_unprepare(core->parent); } +/* clock and it's parents are already prepared/enabled from bootloader, + * so simply record the fact. + */ +static void __clk_inherit_enabled(struct clk_core *core) +{ + core->enable_count++; + core->prepare_count++; +if (core->hw->init->name) // XXX hack.. something funny with xo/xo_board.. + if (core->parent) + __clk_inherit_enabled(core->parent); +} + +void clk_inherit_enabled(struct clk *clk) +{ + __clk_inherit_enabled(clk->core); +} +EXPORT_SYMBOL_GPL(clk_inherit_enabled); + static bool clk_ignore_unused; static int __init clk_ignore_unused_setup(char *__unused) { diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index d523991c945f..90b698c910d0 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -11,6 +11,7 @@ * GNU General Public License for more details. */ +#include #include #include #include @@ -258,6 +259,33 @@ int qcom_cc_really_probe(struct platform_device *pdev, if (ret) return ret; + /* Check which of clocks that we inherit state from bootloader + * are enabled, and fixup enable/prepare state (as well as that + * of it's parents). + * + * TODO can we assume that parents coming from another clk + * driver are already registered? + */ + for (i = 0; i < num_clks; i++) { + struct clk_hw *hw; + + if (!rclks[i]) + continue; + + hw = &rclks[i]->hw; + + if (!(hw->init->flags & CLK_INHERIT_BOOTLOADER)) + continue; + + if (!clk_is_enabled_regmap(hw)) + continue; + + dev_dbg(dev, "%s is enabled from bootloader!\n", + hw->init->name); + + clk_inherit_enabled(hw->clk); + } + reset = &cc->reset; reset->rcdev.of_node = dev->of_node; reset->rcdev.ops = &qcom_reset_ops; diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c index 2cfe7000fc60..c939d33f6377 100644 --- a/drivers/clk/qcom/gcc-msm8916.c +++ b/drivers/clk/qcom/gcc-msm8916.c @@ -2468,7 +2468,7 @@ static struct clk_branch gcc_mdss_ahb_clk = { "pcnoc_bfdcd_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -2485,7 +2485,7 @@ static struct clk_branch gcc_mdss_axi_clk = { "system_noc_bfdcd_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -2502,7 +2502,7 @@ static struct clk_branch gcc_mdss_byte0_clk = { "byte0_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -2519,7 +2519,7 @@ static struct clk_branch gcc_mdss_esc0_clk = { "esc0_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -2536,7 +2536,7 @@ static struct clk_branch gcc_mdss_mdp_clk = { "mdp_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -2553,7 +2553,7 @@ static struct clk_branch gcc_mdss_pclk0_clk = { "pclk0_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -2570,7 +2570,7 @@ static struct clk_branch gcc_mdss_vsync_clk = { "vsync_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -3060,6 +3060,7 @@ static struct gdsc mdss_gdsc = { .name = "mdss", }, .pwrsts = PWRSTS_OFF_ON, + .flags = INHERIT_BL, }; static struct gdsc jpeg_gdsc = { diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index a4f3580587b7..440d819b2d9d 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -291,6 +291,12 @@ static int gdsc_init(struct gdsc *sc) if ((sc->flags & VOTABLE) && on) gdsc_enable(&sc->pd); + if ((sc->flags & INHERIT_BL) && on) { + pr_debug("gdsc: %s is enabled from bootloader!\n", sc->pd.name); + gdsc_enable(&sc->pd); + sc->pd.flags |= GENPD_FLAG_ALWAYS_ON; + } + if (on || (sc->pwrsts & PWRSTS_RET)) gdsc_force_mem_on(sc); else diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h index 39648348e5ec..3b5e64b060c2 100644 --- a/drivers/clk/qcom/gdsc.h +++ b/drivers/clk/qcom/gdsc.h @@ -53,6 +53,7 @@ struct gdsc { #define VOTABLE BIT(0) #define CLAMP_IO BIT(1) #define HW_CTRL BIT(2) +#define INHERIT_BL BIT(3) struct reset_controller_dev *rcdev; unsigned int *resets; unsigned int reset_count; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index c59c62571e4f..4d5505f92329 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -35,6 +35,7 @@ #define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ /* parents need enable during gate/ungate, set rate and re-parent */ #define CLK_OPS_PARENT_ENABLE BIT(12) +#define CLK_INHERIT_BOOTLOADER BIT(13) /* clk may be enabled from bootloader */ struct clk; struct clk_hw; diff --git a/include/linux/clk.h b/include/linux/clk.h index 91bd464f4c9b..461991fc57e2 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -391,6 +391,15 @@ void clk_disable(struct clk *clk); void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks); /** + * clk_inherit_enabled - update the enable/prepare count of a clock and it's + * parents for clock enabled by bootloader. + * + * Intended to be used by clock drivers to inform the clk core of a clock + * that is already running. + */ +void clk_inherit_enabled(struct clk *clk); + +/** * clk_get_rate - obtain the current clock rate (in Hz) for a clock source. * This is only valid once the clock source has been enabled. * @clk: clock source