From patchwork Wed Jan 25 08:19:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Crystal Wood X-Patchwork-Id: 9536517 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 8E42B604A0 for ; Wed, 25 Jan 2017 08:19:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7B4EE27D85 for ; Wed, 25 Jan 2017 08:19:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6FCA927EE9; Wed, 25 Jan 2017 08:19:38 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham 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 DEE0827D9B for ; Wed, 25 Jan 2017 08:19:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751304AbdAYITh (ORCPT ); Wed, 25 Jan 2017 03:19:37 -0500 Received: from host.buserror.net ([209.198.135.123]:59199 "EHLO host.buserror.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751319AbdAYITg (ORCPT ); Wed, 25 Jan 2017 03:19:36 -0500 Received: from c-50-171-225-118.hsd1.mn.comcast.net ([50.171.225.118] helo=snotra.buserror.net) by host.buserror.net with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1cWInl-0003gV-Fs; Wed, 25 Jan 2017 02:19:34 -0600 From: Scott Wood To: Michael Turquette , Stephen Boyd , Shawn Guo Cc: linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org, "Y.B. Lu" , "Z.Q. Hou" , "Y.T. Tang" , Scott Wood Date: Wed, 25 Jan 2017 02:19:23 -0600 Message-Id: <1485332363-8434-3-git-send-email-oss@buserror.net> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1485332363-8434-1-git-send-email-oss@buserror.net> References: <1485332363-8434-1-git-send-email-oss@buserror.net> X-SA-Exim-Connect-IP: 50.171.225.118 X-SA-Exim-Mail-From: oss@buserror.net Subject: [PATCH 3/3] clk: qoriq: Separate root input clock for core PLLs on ls1012a X-SA-Exim-Version: 4.2.1 (built Mon, 26 Dec 2011 16:57:07 +0000) X-SA-Exim-Scanned: Yes (on host.buserror.net) 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 ls1012a has separate input root clocks for core PLLs versus the platform PLL, with the latter described as sysclk in the hw docs. If a second input clock, named "coreclk", is present, this clock will be used for the core PLLs. Signed-off-by: Scott Wood --- drivers/clk/clk-qoriq.c | 91 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 14 deletions(-) diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index d0bf8b1..f3931e3 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c @@ -87,7 +87,7 @@ struct clockgen { struct device_node *node; void __iomem *regs; struct clockgen_chipinfo info; /* mutable copy */ - struct clk *sysclk; + struct clk *sysclk, *coreclk; struct clockgen_pll pll[6]; struct clk *cmux[NUM_CMUX]; struct clk *hwaccel[NUM_HWACCEL]; @@ -904,7 +904,12 @@ static void __init create_muxes(struct clockgen *cg) static void __init clockgen_init(struct device_node *np); -/* Legacy nodes may get probed before the parent clockgen node */ +/* + * Legacy nodes may get probed before the parent clockgen node. + * It is assumed that device trees with legacy nodes will not + * contain a "clocks" property -- otherwise the input clocks may + * not be initialized at this point. + */ static void __init legacy_init_clockgen(struct device_node *np) { if (!clockgen.node) @@ -945,18 +950,13 @@ static struct clk __init return clk_register_fixed_rate(NULL, name, NULL, 0, rate); } -static struct clk *sysclk_from_parent(const char *name) +static struct clk __init *input_clock(const char *name, struct clk *clk) { - struct clk *clk; - const char *parent_name; - - clk = of_clk_get(clockgen.node, 0); - if (IS_ERR(clk)) - return clk; + const char *input_name; /* Register the input clock under the desired name. */ - parent_name = __clk_get_name(clk); - clk = clk_register_fixed_factor(NULL, name, parent_name, + input_name = __clk_get_name(clk); + clk = clk_register_fixed_factor(NULL, name, input_name, 0, 1, 1); if (IS_ERR(clk)) pr_err("%s: Couldn't register %s: %ld\n", __func__, name, @@ -965,6 +965,29 @@ static struct clk *sysclk_from_parent(const char *name) return clk; } +static struct clk __init *input_clock_by_name(const char *name, + const char *dtname) +{ + struct clk *clk; + + clk = of_clk_get_by_name(clockgen.node, dtname); + if (IS_ERR(clk)) + return clk; + + return input_clock(name, clk); +} + +static struct clk __init *input_clock_by_index(const char *name, int idx) +{ + struct clk *clk; + + clk = of_clk_get(clockgen.node, 0); + if (IS_ERR(clk)) + return clk; + + return input_clock(name, clk); +} + static struct clk * __init create_sysclk(const char *name) { struct device_node *sysclk; @@ -974,7 +997,11 @@ static struct clk * __init create_sysclk(const char *name) if (!IS_ERR(clk)) return clk; - clk = sysclk_from_parent(name); + clk = input_clock_by_name(name, "sysclk"); + if (!IS_ERR(clk)) + return clk; + + clk = input_clock_by_index(name, 0); if (!IS_ERR(clk)) return clk; @@ -985,7 +1012,27 @@ static struct clk * __init create_sysclk(const char *name) return clk; } - pr_err("%s: No input clock\n", __func__); + pr_err("%s: No input sysclk\n", __func__); + return NULL; +} + +static struct clk * __init create_coreclk(const char *name) +{ + struct clk *clk; + + clk = input_clock_by_name(name, "coreclk"); + if (!IS_ERR(clk)) + return clk; + + /* + * This indicates a mix of legacy nodes with the new coreclk + * mechanism, which should never happen. If this error occurs, + * don't use the wrong input clock just because coreclk isn't + * ready yet. + */ + if (WARN_ON(PTR_ERR(clk) == -EPROBE_DEFER)) + return clk; + return NULL; } @@ -1008,11 +1055,19 @@ static void __init create_one_pll(struct clockgen *cg, int idx) u32 __iomem *reg; u32 mult; struct clockgen_pll *pll = &cg->pll[idx]; + const char *input = "cg-sysclk"; int i; if (!(cg->info.pll_mask & (1 << idx))) return; + if (cg->coreclk && idx != PLATFORM_PLL) { + if (IS_ERR(cg->coreclk)) + return; + + input = "cg-coreclk"; + } + if (cg->info.flags & CG_VER3) { switch (idx) { case PLATFORM_PLL: @@ -1063,7 +1118,7 @@ static void __init create_one_pll(struct clockgen *cg, int idx) "cg-pll%d-div%d", idx, i + 1); clk = clk_register_fixed_factor(NULL, - pll->div[i].name, "cg-sysclk", 0, mult, i + 1); + pll->div[i].name, input, 0, mult, i + 1); if (IS_ERR(clk)) { pr_err("%s: %s: register failed %ld\n", __func__, pll->div[i].name, PTR_ERR(clk)); @@ -1200,6 +1255,13 @@ static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data) goto bad_args; clk = pll->div[idx].clk; break; + case 5: + if (idx != 0) + goto bad_args; + clk = cg->coreclk; + if (IS_ERR(clk)) + clk = NULL; + break; default: goto bad_args; } @@ -1311,6 +1373,7 @@ static void __init clockgen_init(struct device_node *np) clockgen.info.flags |= CG_CMUX_GE_PLAT; clockgen.sysclk = create_sysclk("cg-sysclk"); + clockgen.coreclk = create_coreclk("cg-coreclk"); create_plls(&clockgen); create_muxes(&clockgen);