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: 9835375 X-Patchwork-Delegate: sboyd@codeaurora.org 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 DA61A602A0 for ; Tue, 11 Jul 2017 18:20:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D008E28567 for ; Tue, 11 Jul 2017 18:20:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C48082856A; Tue, 11 Jul 2017 18:20:27 +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=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 32E2F2856B for ; Tue, 11 Jul 2017 18:20:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756248AbdGKSUZ (ORCPT ); Tue, 11 Jul 2017 14:20:25 -0400 Received: from mail-qt0-f196.google.com ([209.85.216.196]:34124 "EHLO mail-qt0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756107AbdGKSUY (ORCPT ); Tue, 11 Jul 2017 14:20:24 -0400 Received: by mail-qt0-f196.google.com with SMTP id m54so30196qtb.1; 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=ZgRVWW3Kz8dGGr9f9BbpH+jOYSTWRgx9BlLjhtO+FAp6bcDayJBwvkh+ze5dzfwypk YunxkeRbFtoqI2Yfwa8lMDW6wZMMX8oL6BXqfheWeU8ryzFws5ZwOS8RczP+VKlZuM2f hPfidXGYoiNRPa0jmM4oFv1rR7D+BS/LTxtg98riEkkmdoHWQnl7d97gvotEsmvaWk56 zBJns/C0taN8PsHvLb2JGa9cDtoyLb6iuhSyTNrh60b9Vfs2I4X1PcrLimqBT8nljAlC ljxg/CP+TaXJY1qeadCVh+7Uk/IyNM8UPNqq5mTZZJjHuVkaVLXhefYddE9DwYejMC3x S61w== X-Gm-Message-State: AIVw110QgR++4VvVqVtGRq2GjUo/mWrCAxJ73fvAC7UGkq7IhRZwgHid MTMaCnKWUJ39QI5fg44= 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 Cc: Stephen Boyd , Michael Turquette , Archit Taneja , linux-arm-msm@vger.kernel.org, viresh.kumar@linaro.org, Rob Clark 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> Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org 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