From patchwork Tue Jan 29 06:10:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 10785503 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F1D5914E1 for ; Tue, 29 Jan 2019 06:11:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E15C72B63D for ; Tue, 29 Jan 2019 06:11:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D53952B674; Tue, 29 Jan 2019 06:11:13 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 6B6A82B62B for ; Tue, 29 Jan 2019 06:11:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727724AbfA2GLH (ORCPT ); Tue, 29 Jan 2019 01:11:07 -0500 Received: from mail.kernel.org ([198.145.29.99]:33406 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726201AbfA2GKY (ORCPT ); Tue, 29 Jan 2019 01:10:24 -0500 Received: from mail.kernel.org (unknown [104.132.0.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id CAA3B217F5; Tue, 29 Jan 2019 06:10:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1548742223; bh=BO+Wbstcwmn5OrAqlJ976Job1PpJEQEUhPaskYglRTs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vdI7hSj2tMm+x90q9cpjz3Rv3nstjp9HbuNdDuU0WEEmysAkCFqjuHNiZESn/Bc3a I4G+JfT7obn609Zm5zBXxBQu+o6UScm7cVrxS5ko+vW14PRVCfuvzy+ktEH5ujBV+m pF0+dCJYq2XN44qxpPQuO0FV7MZo0D6c259PBcHs= From: Stephen Boyd To: Michael Turquette , Stephen Boyd Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Miquel Raynal , Jerome Brunet , Russell King Subject: [PATCH 1/9] clk: Combine __clk_get() and __clk_create_clk() Date: Mon, 28 Jan 2019 22:10:13 -0800 Message-Id: <20190129061021.94775-2-sboyd@kernel.org> X-Mailer: git-send-email 2.20.1.495.gaa96b0ce6b-goog In-Reply-To: <20190129061021.94775-1-sboyd@kernel.org> References: <20190129061021.94775-1-sboyd@kernel.org> MIME-Version: 1.0 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 __clk_get() function is practically a private clk implementation detail now. No architecture defines it, and given that new code should be using the common clk framework there isn't a need for it to keep existing just to serve clkdev purposes. Let's fold it into the __clk_create_clk() function and make that a little more generic by renaming it to clk_hw_create_clk(). This will allow the framework to create a struct clk handle to a particular clk_hw pointer and link it up as a consumer wherever that's needed. Doing this also lets us get rid of the __clk_free_clk() API that had to be kept in sync with __clk_put(). Splitting that API up into the "link and unlink from consumer list" phase and "free the clk pointer" phase allows us to reuse that logic in a couple places, simplifying the code. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 140 +++++++++++++++++++++++++++++-------------- drivers/clk/clk.h | 10 +--- drivers/clk/clkdev.c | 9 +-- 3 files changed, 98 insertions(+), 61 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index af011974d4ec..01b36f0851bd 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3202,42 +3202,103 @@ static int __clk_core_init(struct clk_core *core) return ret; } -struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id, +/** + * clk_core_link_consumer - Add a clk consumer to the list of consumers in a clk_core + * @core: clk to add consumer to + * @clk: consumer to link to a clk + */ +static void clk_core_link_consumer(struct clk_core *core, struct clk *clk) +{ + clk_prepare_lock(); + hlist_add_head(&clk->clks_node, &core->clks); + clk_prepare_unlock(); +} + +/** + * clk_core_unlink_consumer - Remove a clk consumer from the list of consumers in a clk_core + * @clk: consumer to unlink + */ +static void clk_core_unlink_consumer(struct clk *clk) +{ + lockdep_assert_held(&prepare_lock); + hlist_del(&clk->clks_node); +} + +/** + * alloc_clk - Allocate a clk consumer, but leave it unlinked to the clk_core + * @core: clk to allocate a consumer for + * @dev_id: string describing device name + * @con_id: connection ID string on device + * + * Returns: clk consumer left unlinked from the consumer list + */ +static struct clk *alloc_clk(struct clk_core *core, const char *dev_id, const char *con_id) { struct clk *clk; - /* This is to allow this function to be chained to others */ - if (IS_ERR_OR_NULL(hw)) - return ERR_CAST(hw); - clk = kzalloc(sizeof(*clk), GFP_KERNEL); if (!clk) return ERR_PTR(-ENOMEM); - clk->core = hw->core; + clk->core = core; clk->dev_id = dev_id; clk->con_id = kstrdup_const(con_id, GFP_KERNEL); clk->max_rate = ULONG_MAX; - clk_prepare_lock(); - hlist_add_head(&clk->clks_node, &hw->core->clks); - clk_prepare_unlock(); - return clk; } -/* keep in sync with __clk_put */ -void __clk_free_clk(struct clk *clk) +/** + * free_clk - Free a clk consumer + * @clk: clk consumer to free + * + * Note, this assumes the clk has been unlinked from the clk_core consumer + * list. + */ +static void free_clk(struct clk *clk) { - clk_prepare_lock(); - hlist_del(&clk->clks_node); - clk_prepare_unlock(); - kfree_const(clk->con_id); kfree(clk); } +/** + * clk_hw_create_clk: Allocate and link a clk consumer to a clk_core given + * a clk_hw + * @hw: clk_hw associated with the clk being consumed + * @dev_id: string describing device name + * @con_id: connection ID string on device + * + * This is the main function used to create a clk pointer for use by clk + * consumers. It connects a consumer to the clk_core and clk_hw structures + * used by the framework and clk provider respectively. + */ +struct clk *clk_hw_create_clk(struct clk_hw *hw, + const char *dev_id, const char *con_id) +{ + struct clk *clk; + struct clk_core *core; + + /* This is to allow this function to be chained to others */ + if (IS_ERR_OR_NULL(hw)) + return ERR_CAST(hw); + + core = hw->core; + clk = alloc_clk(core, dev_id, con_id); + if (IS_ERR(clk)) + return clk; + + if (!try_module_get(core->owner)) { + free_clk(clk); + return ERR_PTR(-ENOENT); + } + + kref_get(&core->ref); + clk_core_link_consumer(core, clk); + + return clk; +} + /** * clk_register - allocate a new clock, register it and return an opaque cookie * @dev: device that is registering this clock @@ -3313,17 +3374,27 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) INIT_HLIST_HEAD(&core->clks); - hw->clk = __clk_create_clk(hw, NULL, NULL); + /* + * Don't call clk_hw_create_clk() here because that would pin the + * provider module to itself and prevent it from ever being removed. + */ + hw->clk = alloc_clk(core, NULL, NULL); if (IS_ERR(hw->clk)) { ret = PTR_ERR(hw->clk); goto fail_parents; } + clk_core_link_consumer(hw->core, hw->clk); + ret = __clk_core_init(core); if (!ret) return hw->clk; - __clk_free_clk(hw->clk); + clk_prepare_lock(); + clk_core_unlink_consumer(hw->clk); + clk_prepare_unlock(); + + free_clk(hw->clk); hw->clk = NULL; fail_parents: @@ -3594,20 +3665,7 @@ EXPORT_SYMBOL_GPL(devm_clk_hw_unregister); /* * clkdev helpers */ -int __clk_get(struct clk *clk) -{ - struct clk_core *core = !clk ? NULL : clk->core; - - if (core) { - if (!try_module_get(core->owner)) - return 0; - - kref_get(&core->ref); - } - return 1; -} -/* keep in sync with __clk_free_clk */ void __clk_put(struct clk *clk) { struct module *owner; @@ -3641,8 +3699,7 @@ void __clk_put(struct clk *clk) module_put(owner); - kfree_const(clk->con_id); - kfree(clk); + free_clk(clk); } /*** clk rate change notifiers ***/ @@ -3980,8 +4037,7 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, const char *dev_id, const char *con_id) { struct of_clk_provider *provider; - struct clk *clk = ERR_PTR(-EPROBE_DEFER); - struct clk_hw *hw; + struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); if (!clkspec) return ERR_PTR(-EINVAL); @@ -3991,21 +4047,13 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, list_for_each_entry(provider, &of_clk_providers, link) { if (provider->node == clkspec->np) { hw = __of_clk_get_hw_from_provider(provider, clkspec); - clk = __clk_create_clk(hw, dev_id, con_id); - } - - if (!IS_ERR(clk)) { - if (!__clk_get(clk)) { - __clk_free_clk(clk); - clk = ERR_PTR(-ENOENT); - } - - break; + if (!IS_ERR(hw)) + break; } } mutex_unlock(&of_clk_mutex); - return clk; + return clk_hw_create_clk(hw, dev_id, con_id); } /** diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h index 70c0ba6336c1..c9a14122fadc 100644 --- a/drivers/clk/clk.h +++ b/drivers/clk/clk.h @@ -17,24 +17,20 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, #endif #ifdef CONFIG_COMMON_CLK -struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id, - const char *con_id); -void __clk_free_clk(struct clk *clk); -int __clk_get(struct clk *clk); +struct clk *clk_hw_create_clk(struct clk_hw *hw, + const char *dev_id, const char *con_id); void __clk_put(struct clk *clk); #else /* All these casts to avoid ifdefs in clkdev... */ static inline struct clk * -__clk_create_clk(struct clk_hw *hw, const char *dev_id, const char *con_id) +clk_hw_create_clk(struct clk_hw *hw, const char *dev_id, const char *con_id) { return (struct clk *)hw; } -static inline void __clk_free_clk(struct clk *clk) { } static struct clk_hw *__clk_get_hw(struct clk *clk) { return (struct clk_hw *)clk; } -static inline int __clk_get(struct clk *clk) { return 1; } static inline void __clk_put(struct clk *clk) { } #endif diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 9ab3db8b3988..bdeaffc950ae 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -174,16 +174,9 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id) if (!cl) goto out; - clk = __clk_create_clk(cl->clk_hw, dev_id, con_id); + clk = clk_hw_create_clk(cl->clk_hw, dev_id, con_id); if (IS_ERR(clk)) - goto out; - - if (!__clk_get(clk)) { - __clk_free_clk(clk); cl = NULL; - goto out; - } - out: mutex_unlock(&clocks_mutex); From patchwork Tue Jan 29 06:10:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 10785499 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AC0FF91E for ; Tue, 29 Jan 2019 06:11:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9DAE42B655 for ; Tue, 29 Jan 2019 06:11:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 91FE82B67A; Tue, 29 Jan 2019 06:11:00 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 D3AAE2B630 for ; Tue, 29 Jan 2019 06:10:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727359AbfA2GKZ (ORCPT ); Tue, 29 Jan 2019 01:10:25 -0500 Received: from mail.kernel.org ([198.145.29.99]:33426 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726217AbfA2GKY (ORCPT ); Tue, 29 Jan 2019 01:10:24 -0500 Received: from mail.kernel.org (unknown [104.132.0.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 37B312183F; Tue, 29 Jan 2019 06:10:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1548742223; bh=i2/x4THMEQuaCq9FeqNFX7loZmXx3MGcTTPWunJFV3Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qIJXt5K5UO+J5+NRKWV0ajCMxvEFXgGUuxeeVL3Nu7mwJZ//9OOV4M2z8NVWrhwie FUwrlTSVN6FJH5HcxDzPyBYnpwRHoipkUbI8XxSXiN9IIK7I5/D0a5Au4gHRRq3Nc+ Ck1sxSDOoZ+dsynGsc6HKkuUJ8Yzjr5Bo5d83h/k= From: Stephen Boyd To: Michael Turquette , Stephen Boyd Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Miquel Raynal , Jerome Brunet , Russell King Subject: [PATCH 2/9] clk: Introduce get_parent_hw clk op Date: Mon, 28 Jan 2019 22:10:14 -0800 Message-Id: <20190129061021.94775-3-sboyd@kernel.org> X-Mailer: git-send-email 2.20.1.495.gaa96b0ce6b-goog In-Reply-To: <20190129061021.94775-1-sboyd@kernel.org> References: <20190129061021.94775-1-sboyd@kernel.org> MIME-Version: 1.0 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 clk_ops::get_parent function is limited in ability to return errors because it returns a u8. A "workaround" to return an error is to return a number >= the number of parents of a clk. This will in turn cause the framework to "orphan" the clk and make the parent of the clk NULL. This isn't really correct, because if an error occurs while reading the parents of a clk we should fail the clk registration, instead of orphaning the clk and waiting for the clk to appear later. We really need to have three different return values from the get_parent clk op. Something valid for a clk that exists, something invalid for a clk that doesn't exist and never will exist or can't be determined because the register operation to read the parent failed, and something for a clk that doesn't exist because the framework doesn't know about what it is. Introduce a new clk_op that can express all of this by returning a pointer to the clk_hw of the parent. It's expected that clk provider drivers will return a valid pointer when the parent is findable, an error pointer like EPROBE_DEFER if their parent provider hasn't probed yet but is valid, a NULL pointer if they can't find the clk but index is valid, and an error pointer with an appropriate error code otherwise. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 117 ++++++++++++++++++++++++++--------- include/linux/clk-provider.h | 9 +++ 2 files changed, 96 insertions(+), 30 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 01b36f0851bd..5d82cf25bb29 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2242,14 +2242,84 @@ struct clk *clk_get_parent(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_get_parent); -static struct clk_core *__clk_init_parent(struct clk_core *core) +static struct clk_core * +__clk_init_parent(struct clk_core *core, bool update_orphan) { u8 index = 0; + struct clk_hw *parent_hw = NULL; - if (core->num_parents > 1 && core->ops->get_parent) - index = core->ops->get_parent(core->hw); + if (core->ops->get_parent_hw) { + parent_hw = core->ops->get_parent_hw(core->hw); + /* + * The provider driver doesn't know what the parent is, + * but it's at least something valid, so it's not an + * orphan, just a clk with some unknown parent. + */ + if (!parent_hw && update_orphan) + core->orphan = false; + } else { + if (core->num_parents > 1 && core->ops->get_parent) + index = core->ops->get_parent(core->hw); + + parent_hw = clk_hw_get_parent_by_index(core->hw, index); + } + + if (IS_ERR(parent_hw)) { + /* Parent clk provider hasn't probed yet, orphan it */ + if (PTR_ERR(parent_hw) == -EPROBE_DEFER) { + if (update_orphan) + core->orphan = true; + + return NULL; + } + + return ERR_CAST(parent_hw); + } + + if (!parent_hw) + return NULL; + + return parent_hw->core; +} + +static int clk_init_parent(struct clk_core *core) +{ + core->parent = __clk_init_parent(core, true); + if (IS_ERR(core->parent)) + return PTR_ERR(core->parent); + + /* + * Populate core->parent if parent has already been clk_core_init'd. If + * parent has not yet been clk_core_init'd then place clk in the orphan + * list. If clk doesn't have any parents then place it in the root + * clk list. + * + * Every time a new clk is clk_init'd then we walk the list of orphan + * clocks and re-parent any that are children of the clock currently + * being clk_init'd. + */ + if (core->parent) { + hlist_add_head(&core->child_node, + &core->parent->children); + core->orphan = core->parent->orphan; + } else if (!core->num_parents) { + hlist_add_head(&core->child_node, &clk_root_list); + core->orphan = false; + } else { + hlist_add_head(&core->child_node, &clk_orphan_list); + } + + return 0; +} - return clk_core_get_parent_by_index(core, index); +static struct clk_core *clk_find_parent(struct clk_core *core) +{ + return __clk_init_parent(core, false); +} + +static bool clk_has_parent_op(const struct clk_ops *ops) +{ + return ops->get_parent || ops->get_parent_hw; } static void clk_core_reparent(struct clk_core *core, @@ -3045,14 +3115,14 @@ static int __clk_core_init(struct clk_core *core) goto out; } - if (core->ops->set_parent && !core->ops->get_parent) { + if (core->ops->set_parent && !clk_has_parent_op(core->ops)) { pr_err("%s: %s must implement .get_parent & .set_parent\n", __func__, core->name); ret = -EINVAL; goto out; } - if (core->num_parents > 1 && !core->ops->get_parent) { + if (core->num_parents > 1 && !clk_has_parent_op(core->ops)) { pr_err("%s: %s must implement .get_parent as it has multi parents\n", __func__, core->name); ret = -EINVAL; @@ -3073,29 +3143,9 @@ static int __clk_core_init(struct clk_core *core) "%s: invalid NULL in %s's .parent_names\n", __func__, core->name); - core->parent = __clk_init_parent(core); - - /* - * Populate core->parent if parent has already been clk_core_init'd. If - * parent has not yet been clk_core_init'd then place clk in the orphan - * list. If clk doesn't have any parents then place it in the root - * clk list. - * - * Every time a new clk is clk_init'd then we walk the list of orphan - * clocks and re-parent any that are children of the clock currently - * being clk_init'd. - */ - if (core->parent) { - hlist_add_head(&core->child_node, - &core->parent->children); - core->orphan = core->parent->orphan; - } else if (!core->num_parents) { - hlist_add_head(&core->child_node, &clk_root_list); - core->orphan = false; - } else { - hlist_add_head(&core->child_node, &clk_orphan_list); - core->orphan = true; - } + ret = clk_init_parent(core); + if (ret) + goto out; /* * optional platform-specific magic @@ -3173,7 +3223,14 @@ static int __clk_core_init(struct clk_core *core) * parent. */ hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) { - struct clk_core *parent = __clk_init_parent(orphan); + struct clk_core *parent = clk_find_parent(orphan); + + /* + * Error parent should have been caught before and returned + * as an error during registration. + */ + if (WARN_ON_ONCE(IS_ERR(parent))) + continue; /* * We need to use __clk_set_parent_before() and _after() to diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 60c51871b04b..8b84dee942bf 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -155,6 +155,14 @@ struct clk_duty { * multiple parents. It is optional (and unnecessary) for clocks * with 0 or 1 parents. * + * @get_parent_hw: Queries the hardware to determine the parent of a clock. The + * return value is a clk_hw pointer corresponding to + * the parent clock. In short, this function translates the parent + * value read from hardware into a pointer to the clk_hw for that clk. + * Currently only called when the clock is initialized by + * __clk_init. This callback is mandatory for clocks with + * multiple parents. It is optional for clocks with 0 or 1 parents. + * * @set_rate: Change the rate of this clock. The requested rate is specified * by the second argument, which should typically be the return * of .round_rate call. The third argument gives the parent rate @@ -238,6 +246,7 @@ struct clk_ops { struct clk_rate_request *req); int (*set_parent)(struct clk_hw *hw, u8 index); u8 (*get_parent)(struct clk_hw *hw); + struct clk_hw * (*get_parent_hw)(struct clk_hw *hw); int (*set_rate)(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate); int (*set_rate_and_parent)(struct clk_hw *hw, From patchwork Tue Jan 29 06:10:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 10785501 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 76A4814E1 for ; Tue, 29 Jan 2019 06:11:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 691FC2B484 for ; Tue, 29 Jan 2019 06:11:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5DE862B682; Tue, 29 Jan 2019 06:11:01 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 DC3A62B67A for ; Tue, 29 Jan 2019 06:11:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725832AbfA2GLA (ORCPT ); Tue, 29 Jan 2019 01:11:00 -0500 Received: from mail.kernel.org ([198.145.29.99]:33430 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726230AbfA2GKY (ORCPT ); Tue, 29 Jan 2019 01:10:24 -0500 Received: from mail.kernel.org (unknown [104.132.0.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 9120E21841; Tue, 29 Jan 2019 06:10:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1548742223; bh=Z848HCBtnzeyslpUOhB1zGR5r1IbxympifhvWGT6J3A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=V+Jo7mWUqfz1ur1wEqNpUO+8yeyp2rRAvnsgH9ICjO599S1Hyz+Mw16aIXCWFpYI6 Z4f9BckDZfClGF0Lls2HaCYLOSzWbIWVBzQfUSCG4JeHbPwkou36Ck6fwLm1gqOix7 4Fq6H11JRg0KwEziBjZu7VOl+CZwN15sTo+HBhCU= From: Stephen Boyd To: Michael Turquette , Stephen Boyd Cc: Miquel Raynal , linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Jerome Brunet , Russell King Subject: [PATCH 3/9] clk: core: clarify the check for runtime PM Date: Mon, 28 Jan 2019 22:10:15 -0800 Message-Id: <20190129061021.94775-4-sboyd@kernel.org> X-Mailer: git-send-email 2.20.1.495.gaa96b0ce6b-goog In-Reply-To: <20190129061021.94775-1-sboyd@kernel.org> References: <20190129061021.94775-1-sboyd@kernel.org> MIME-Version: 1.0 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 From: Miquel Raynal Currently, the core->dev entry is populated only if runtime PM is enabled. Doing so prevents accessing the device structure in any case. Keep the same logic but instead of using the presence of core->dev as the only condition, also check the status of pm_runtime_enabled(). Then, we can set the core->dev pointer at any time as long as a device structure is available. This change will help supporting device links in the clock subsystem. Signed-off-by: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette [sboyd@kernel.org: Change to a boolean flag] Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 5d82cf25bb29..01cdb9ae03fa 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -60,6 +60,7 @@ struct clk_core { struct clk_core *new_child; unsigned long flags; bool orphan; + bool rpm_enabled; unsigned int enable_count; unsigned int prepare_count; unsigned int protect_count; @@ -95,9 +96,9 @@ struct clk { /*** runtime pm ***/ static int clk_pm_runtime_get(struct clk_core *core) { - int ret = 0; + int ret; - if (!core->dev) + if (!core->rpm_enabled) return 0; ret = pm_runtime_get_sync(core->dev); @@ -106,7 +107,7 @@ static int clk_pm_runtime_get(struct clk_core *core) static void clk_pm_runtime_put(struct clk_core *core) { - if (!core->dev) + if (!core->rpm_enabled) return; pm_runtime_put_sync(core->dev); @@ -226,7 +227,7 @@ static bool clk_core_is_enabled(struct clk_core *core) * taking enable spinlock, but the below check is needed if one tries * to call it from other places. */ - if (core->dev) { + if (core->rpm_enabled) { pm_runtime_get_noresume(core->dev); if (!pm_runtime_active(core->dev)) { ret = false; @@ -236,7 +237,7 @@ static bool clk_core_is_enabled(struct clk_core *core) ret = core->ops->is_enabled(core->hw); done: - if (core->dev) + if (core->rpm_enabled) pm_runtime_put(core->dev); return ret; @@ -3391,7 +3392,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) core->ops = hw->init->ops; if (dev && pm_runtime_enabled(dev)) - core->dev = dev; + core->rpm_enabled = true; + core->dev = dev; if (dev && dev->driver) core->owner = dev->driver->owner; core->hw = hw; From patchwork Tue Jan 29 06:10:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 10785495 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CDD7291E for ; Tue, 29 Jan 2019 06:10:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BD2E32B62D for ; Tue, 29 Jan 2019 06:10:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B148A2B62B; Tue, 29 Jan 2019 06:10:52 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 F155A2B663 for ; Tue, 29 Jan 2019 06:10:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727446AbfA2GK0 (ORCPT ); Tue, 29 Jan 2019 01:10:26 -0500 Received: from mail.kernel.org ([198.145.29.99]:33440 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726799AbfA2GKZ (ORCPT ); Tue, 29 Jan 2019 01:10:25 -0500 Received: from mail.kernel.org (unknown [104.132.0.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id E9D9921848; Tue, 29 Jan 2019 06:10:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1548742224; bh=xpJjqVk08G7KRA5XNG0b5SrlCMynjA4/zEzEaDe3N0I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZJC2IYe+v9rw/dx+ZZJFMyshaWLsNA1RnJPBoqxD7sxTSgkoGKoCRLE3V6e0h8VOY Gr762PUjpraoCaHrnIYWVXWtxRcK0RySv+/XtbRiuWS02iplISuK1ZVY8DI21zrNFy mP4oQPSChkRMFXy5YmGzMu4PUnbXy3fcWXqCHlmI= From: Stephen Boyd To: Michael Turquette , Stephen Boyd Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Miquel Raynal , Jerome Brunet , Russell King Subject: [PATCH 4/9] clk: Introduce of_clk_get_hw_from_clkspec() Date: Mon, 28 Jan 2019 22:10:16 -0800 Message-Id: <20190129061021.94775-5-sboyd@kernel.org> X-Mailer: git-send-email 2.20.1.495.gaa96b0ce6b-goog In-Reply-To: <20190129061021.94775-1-sboyd@kernel.org> References: <20190129061021.94775-1-sboyd@kernel.org> MIME-Version: 1.0 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 We want to get struct clk_hw pointers from a DT clk specifier (i.e. a clocks property) so that we can find parent clks without searching for globally unique clk names. This should save time by avoiding the global string search for clks that are external to the clock controller providing the clk and let us move away from string comparisons in general. Introduce of_clk_get_hw_from_clkspec() which is largely the DT parsing part of finding clks implemented in clkdev.c and have that return a clk_hw pointer instead of converting that into a clk pointer. This lets us push up the clk pointer creation to the caller in clk_get() and avoids the need to push the dev_id and con_id throughout the DT parsing code. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 46 +++++++++++++++++++++--- drivers/clk/clk.h | 5 +-- drivers/clk/clkdev.c | 83 +++++++++++++------------------------------- 3 files changed, 69 insertions(+), 65 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 01cdb9ae03fa..d4c4cab42375 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4077,6 +4077,42 @@ void devm_of_clk_del_provider(struct device *dev) } EXPORT_SYMBOL(devm_of_clk_del_provider); +int of_parse_clkspec(const struct device_node *np, int index, const char *name, + struct of_phandle_args *out_args) +{ + int ret = -ENOENT; + + /* Walk up the tree of devices looking for a clock property that matches */ + while (np) { + /* + * For named clocks, first look up the name in the + * "clock-names" property. If it cannot be found, then index + * will be an error code and of_parse_phandle_with_args() will + * return -EINVAL. + */ + if (name) + index = of_property_match_string(np, "clock-names", name); + ret = of_parse_phandle_with_args(np, "clocks", "#clock-cells", + index, out_args); + if (!ret) + break; + if (name && index >= 0) + break; + + /* + * No matching clock found on this node. If the parent node + * has a "clock-ranges" property, then we can try one of its + * clocks. + */ + np = np->parent; + if (np && !of_get_property(np, "clock-ranges", NULL)) + break; + index = 0; + } + + return ret; +} + static struct clk_hw * __of_clk_get_hw_from_provider(struct of_clk_provider *provider, struct of_phandle_args *clkspec) @@ -4092,8 +4128,7 @@ __of_clk_get_hw_from_provider(struct of_clk_provider *provider, return __clk_get_hw(clk); } -struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, - const char *dev_id, const char *con_id) +struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec) { struct of_clk_provider *provider; struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); @@ -4101,7 +4136,6 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, if (!clkspec) return ERR_PTR(-EINVAL); - /* Check if we have such a provider in our array */ mutex_lock(&of_clk_mutex); list_for_each_entry(provider, &of_clk_providers, link) { if (provider->node == clkspec->np) { @@ -4112,7 +4146,7 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, } mutex_unlock(&of_clk_mutex); - return clk_hw_create_clk(hw, dev_id, con_id); + return hw; } /** @@ -4125,7 +4159,9 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, */ struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) { - return __of_clk_get_from_provider(clkspec, NULL, __func__); + struct clk_hw *hw = of_clk_get_hw_from_clkspec(clkspec); + + return clk_hw_create_clk(hw, NULL, __func__); } EXPORT_SYMBOL_GPL(of_clk_get_from_provider); diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h index c9a14122fadc..cdac6dfa8094 100644 --- a/drivers/clk/clk.h +++ b/drivers/clk/clk.h @@ -12,8 +12,9 @@ struct clk_hw; #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) -struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, - const char *dev_id, const char *con_id); +int of_parse_clkspec(const struct device_node *np, int index, const char *name, + struct of_phandle_args *out_args); +struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec); #endif #ifdef CONFIG_COMMON_CLK diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index bdeaffc950ae..5ebb2119c0b9 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -28,69 +28,37 @@ static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) -static struct clk *__of_clk_get(struct device_node *np, int index, - const char *dev_id, const char *con_id) +static struct clk_hw *of_clk_get_hw(struct device_node *np, + int index, const char *con_id) { + int ret; + struct clk_hw *hw; struct of_phandle_args clkspec; - struct clk *clk; - int rc; - rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index, - &clkspec); - if (rc) - return ERR_PTR(rc); + ret = of_parse_clkspec(np, index, con_id, &clkspec); + if (ret) + return ERR_PTR(ret); - clk = __of_clk_get_from_provider(&clkspec, dev_id, con_id); + hw = of_clk_get_hw_from_clkspec(&clkspec); of_node_put(clkspec.np); - return clk; + return hw; } -struct clk *of_clk_get(struct device_node *np, int index) +static struct clk *__of_clk_get(struct device_node *np, + int index, const char *dev_id, + const char *con_id) { - return __of_clk_get(np, index, np->full_name, NULL); + struct clk_hw *hw = of_clk_get_hw(np, index, con_id); + + return clk_hw_create_clk(hw, dev_id, con_id); } -EXPORT_SYMBOL(of_clk_get); -static struct clk *__of_clk_get_by_name(struct device_node *np, - const char *dev_id, - const char *name) +struct clk *of_clk_get(struct device_node *np, int index) { - struct clk *clk = ERR_PTR(-ENOENT); - - /* Walk up the tree of devices looking for a clock that matches */ - while (np) { - int index = 0; - - /* - * For named clocks, first look up the name in the - * "clock-names" property. If it cannot be found, then - * index will be an error code, and of_clk_get() will fail. - */ - if (name) - index = of_property_match_string(np, "clock-names", name); - clk = __of_clk_get(np, index, dev_id, name); - if (!IS_ERR(clk)) { - break; - } else if (name && index >= 0) { - if (PTR_ERR(clk) != -EPROBE_DEFER) - pr_err("ERROR: could not get clock %pOF:%s(%i)\n", - np, name ? name : "", index); - return clk; - } - - /* - * No matching clock found on this node. If the parent node - * has a "clock-ranges" property, then we can try one of its - * clocks. - */ - np = np->parent; - if (np && !of_get_property(np, "clock-ranges", NULL)) - break; - } - - return clk; + return __of_clk_get(np, index, np->full_name, NULL); } +EXPORT_SYMBOL(of_clk_get); /** * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node @@ -106,15 +74,14 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name) if (!np) return ERR_PTR(-ENOENT); - return __of_clk_get_by_name(np, np->full_name, name); + return __of_clk_get(np, -1, np->full_name, name); } EXPORT_SYMBOL(of_clk_get_by_name); #else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */ -static struct clk *__of_clk_get_by_name(struct device_node *np, - const char *dev_id, - const char *name) +static struct clk_hw *of_clk_get_hw(struct device_node *np, + int index, const char *con_id) { return ERR_PTR(-ENOENT); } @@ -187,12 +154,12 @@ EXPORT_SYMBOL(clk_get_sys); struct clk *clk_get(struct device *dev, const char *con_id) { const char *dev_id = dev ? dev_name(dev) : NULL; - struct clk *clk; + struct clk_hw *hw; if (dev && dev->of_node) { - clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id); - if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER) - return clk; + hw = of_clk_get_hw(dev->of_node, 0, con_id); + if (!IS_ERR(hw) || PTR_ERR(hw) == -EPROBE_DEFER) + return clk_hw_create_clk(hw, dev_id, con_id); } return clk_get_sys(dev_id, con_id); From patchwork Tue Jan 29 06:10:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 10785497 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EA94091E for ; Tue, 29 Jan 2019 06:10:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DCB022B625 for ; Tue, 29 Jan 2019 06:10:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D115B2B67A; Tue, 29 Jan 2019 06:10:57 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 4387D2B67A for ; Tue, 29 Jan 2019 06:10:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726292AbfA2GKw (ORCPT ); Tue, 29 Jan 2019 01:10:52 -0500 Received: from mail.kernel.org ([198.145.29.99]:33450 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725832AbfA2GK0 (ORCPT ); Tue, 29 Jan 2019 01:10:26 -0500 Received: from mail.kernel.org (unknown [104.132.0.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 4ED102184D; Tue, 29 Jan 2019 06:10:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1548742224; bh=M+W9UixXghcZ2tQo1f3291ReSl8cVMi29InxnarTtdw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=otJTGT/9KbicncNoFfTcIJPsST9iDaNbuERW4fqLWz/bpD/WTuOJokbmivJaoCBNm JrWXJ3qYazdCA9ETdJBQmJHtEWLxSPtZsnJ8XydL+JYLNQ+55LbaWbxYdLX2ona6ko +l+d+sFLEX4dLKkW4Q8/vtDRac06nudsDwC7fcQE= From: Stephen Boyd To: Michael Turquette , Stephen Boyd Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Miquel Raynal , Jerome Brunet , Russell King Subject: [PATCH 5/9] clk: Inform the core about consumer devices Date: Mon, 28 Jan 2019 22:10:17 -0800 Message-Id: <20190129061021.94775-6-sboyd@kernel.org> X-Mailer: git-send-email 2.20.1.495.gaa96b0ce6b-goog In-Reply-To: <20190129061021.94775-1-sboyd@kernel.org> References: <20190129061021.94775-1-sboyd@kernel.org> MIME-Version: 1.0 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 We'd like to have a pointer to the device that's consuming a particular clk in the clk framework so we can link the consumer to the clk provider with a PM device link. Add a device argument to clk_hw_create_clk() for this so it can be used in subsequent patches to add and remove the link. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 7 +++++-- drivers/clk/clk.h | 7 +++++-- drivers/clk/clkdev.c | 16 +++++++++++----- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index d4c4cab42375..73f8a287bf42 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -85,6 +85,7 @@ struct clk_core { struct clk { struct clk_core *core; + struct device *dev; const char *dev_id; const char *con_id; unsigned long min_rate; @@ -3323,6 +3324,7 @@ static void free_clk(struct clk *clk) /** * clk_hw_create_clk: Allocate and link a clk consumer to a clk_core given * a clk_hw + * @dev: clk consumer device * @hw: clk_hw associated with the clk being consumed * @dev_id: string describing device name * @con_id: connection ID string on device @@ -3331,7 +3333,7 @@ static void free_clk(struct clk *clk) * consumers. It connects a consumer to the clk_core and clk_hw structures * used by the framework and clk provider respectively. */ -struct clk *clk_hw_create_clk(struct clk_hw *hw, +struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id, const char *con_id) { struct clk *clk; @@ -3345,6 +3347,7 @@ struct clk *clk_hw_create_clk(struct clk_hw *hw, clk = alloc_clk(core, dev_id, con_id); if (IS_ERR(clk)) return clk; + clk->dev = dev; if (!try_module_get(core->owner)) { free_clk(clk); @@ -4161,7 +4164,7 @@ struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) { struct clk_hw *hw = of_clk_get_hw_from_clkspec(clkspec); - return clk_hw_create_clk(hw, NULL, __func__); + return clk_hw_create_clk(NULL, hw, NULL, __func__); } EXPORT_SYMBOL_GPL(of_clk_get_from_provider); diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h index cdac6dfa8094..fda0ad483416 100644 --- a/drivers/clk/clk.h +++ b/drivers/clk/clk.h @@ -10,6 +10,8 @@ */ struct clk_hw; +struct device; +struct of_phandle_args; #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) int of_parse_clkspec(const struct device_node *np, int index, const char *name, @@ -18,13 +20,14 @@ struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec); #endif #ifdef CONFIG_COMMON_CLK -struct clk *clk_hw_create_clk(struct clk_hw *hw, +struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id, const char *con_id); void __clk_put(struct clk *clk); #else /* All these casts to avoid ifdefs in clkdev... */ static inline struct clk * -clk_hw_create_clk(struct clk_hw *hw, const char *dev_id, const char *con_id) +clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id, + const char *con_id) { return (struct clk *)hw; } diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 5ebb2119c0b9..f2f4f2afd28c 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -51,7 +51,7 @@ static struct clk *__of_clk_get(struct device_node *np, { struct clk_hw *hw = of_clk_get_hw(np, index, con_id); - return clk_hw_create_clk(hw, dev_id, con_id); + return clk_hw_create_clk(NULL, hw, dev_id, con_id); } struct clk *of_clk_get(struct device_node *np, int index) @@ -130,7 +130,8 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) return cl; } -struct clk *clk_get_sys(const char *dev_id, const char *con_id) +static struct clk *__clk_get_sys(struct device *dev, const char *dev_id, + const char *con_id) { struct clk_lookup *cl; struct clk *clk = NULL; @@ -141,7 +142,7 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id) if (!cl) goto out; - clk = clk_hw_create_clk(cl->clk_hw, dev_id, con_id); + clk = clk_hw_create_clk(dev, cl->clk_hw, dev_id, con_id); if (IS_ERR(clk)) cl = NULL; out: @@ -149,6 +150,11 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id) return cl ? clk : ERR_PTR(-ENOENT); } + +struct clk *clk_get_sys(const char *dev_id, const char *con_id) +{ + return __clk_get_sys(NULL, dev_id, con_id); +} EXPORT_SYMBOL(clk_get_sys); struct clk *clk_get(struct device *dev, const char *con_id) @@ -159,10 +165,10 @@ struct clk *clk_get(struct device *dev, const char *con_id) if (dev && dev->of_node) { hw = of_clk_get_hw(dev->of_node, 0, con_id); if (!IS_ERR(hw) || PTR_ERR(hw) == -EPROBE_DEFER) - return clk_hw_create_clk(hw, dev_id, con_id); + return clk_hw_create_clk(dev, hw, dev_id, con_id); } - return clk_get_sys(dev_id, con_id); + return __clk_get_sys(dev, dev_id, con_id); } EXPORT_SYMBOL(clk_get); From patchwork Tue Jan 29 06:10:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 10785487 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A2F8F14E1 for ; Tue, 29 Jan 2019 06:10:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 94E302B630 for ; Tue, 29 Jan 2019 06:10:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 89BDC2B62D; Tue, 29 Jan 2019 06:10:29 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 EA4AA2B482 for ; Tue, 29 Jan 2019 06:10:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727557AbfA2GK1 (ORCPT ); Tue, 29 Jan 2019 01:10:27 -0500 Received: from mail.kernel.org ([198.145.29.99]:33466 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727366AbfA2GK0 (ORCPT ); Tue, 29 Jan 2019 01:10:26 -0500 Received: from mail.kernel.org (unknown [104.132.0.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id A847921852; Tue, 29 Jan 2019 06:10:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1548742224; bh=lqLBOdLs/K2ek01660gtvK/N+IUXOeXI9jrcvENBlWY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=chkEP6cppO4jcoYJRpIBRwEPEaqQfaGd2idjH2On/oB7oxgRCVcbTMnfSWQVbsNA6 z8p+0MM6Km1b2dwN2svWuMhXWQvGTGUwcC2bHP/ZhJcPBABJEwV2gMybJ6/08aMYAt /sMBeBBtCvU2vQZtlpaVNKQPK7islN9FscGSRh9Y= From: Stephen Boyd To: Michael Turquette , Stephen Boyd Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Miquel Raynal , Jerome Brunet , Russell King Subject: [PATCH 6/9] clk: Move of_clk_*() APIs into clk.c from clkdev.c Date: Mon, 28 Jan 2019 22:10:18 -0800 Message-Id: <20190129061021.94775-7-sboyd@kernel.org> X-Mailer: git-send-email 2.20.1.495.gaa96b0ce6b-goog In-Reply-To: <20190129061021.94775-1-sboyd@kernel.org> References: <20190129061021.94775-1-sboyd@kernel.org> MIME-Version: 1.0 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 API between clk.c and clkdev.c is purely getting the clk_hw structure (or the struct clk if it's not CCF) and then turning that struct clk_hw pointer into a struct clk pointer via clk_hw_create_clk(). There's no need to complicate clkdev.c with these DT parsing details that are only relevant to the common clk framework. Move the DT parsing logic into the core framework and just expose the APIs to get a clk_hw pointer and convert it. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 57 ++++++++++++++++++++++++++++++++++++++--- drivers/clk/clk.h | 11 +++++--- drivers/clk/clkdev.c | 60 -------------------------------------------- 3 files changed, 62 insertions(+), 66 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 73f8a287bf42..202902e64799 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4080,8 +4080,8 @@ void devm_of_clk_del_provider(struct device *dev) } EXPORT_SYMBOL(devm_of_clk_del_provider); -int of_parse_clkspec(const struct device_node *np, int index, const char *name, - struct of_phandle_args *out_args) +static int of_parse_clkspec(const struct device_node *np, int index, + const char *name, struct of_phandle_args *out_args) { int ret = -ENOENT; @@ -4131,7 +4131,8 @@ __of_clk_get_hw_from_provider(struct of_clk_provider *provider, return __clk_get_hw(clk); } -struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec) +static struct clk_hw * +of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec) { struct of_clk_provider *provider; struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); @@ -4168,6 +4169,56 @@ struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) } EXPORT_SYMBOL_GPL(of_clk_get_from_provider); +struct clk_hw *of_clk_get_hw(struct device_node *np, int index, + const char *con_id) +{ + int ret; + struct clk_hw *hw; + struct of_phandle_args clkspec; + + ret = of_parse_clkspec(np, index, con_id, &clkspec); + if (ret) + return ERR_PTR(ret); + + hw = of_clk_get_hw_from_clkspec(&clkspec); + of_node_put(clkspec.np); + + return hw; +} + +static struct clk *__of_clk_get(struct device_node *np, + int index, const char *dev_id, + const char *con_id) +{ + struct clk_hw *hw = of_clk_get_hw(np, index, con_id); + + return clk_hw_create_clk(NULL, hw, dev_id, con_id); +} + +struct clk *of_clk_get(struct device_node *np, int index) +{ + return __of_clk_get(np, index, np->full_name, NULL); +} +EXPORT_SYMBOL(of_clk_get); + +/** + * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node + * @np: pointer to clock consumer node + * @name: name of consumer's clock input, or NULL for the first clock reference + * + * This function parses the clocks and clock-names properties, + * and uses them to look up the struct clk from the registered list of clock + * providers. + */ +struct clk *of_clk_get_by_name(struct device_node *np, const char *name) +{ + if (!np) + return ERR_PTR(-ENOENT); + + return __of_clk_get(np, -1, np->full_name, name); +} +EXPORT_SYMBOL(of_clk_get_by_name); + /** * of_clk_get_parent_count() - Count the number of clocks a device node has * @np: device node to count diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h index fda0ad483416..46e668d64da8 100644 --- a/drivers/clk/clk.h +++ b/drivers/clk/clk.h @@ -14,9 +14,14 @@ struct device; struct of_phandle_args; #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) -int of_parse_clkspec(const struct device_node *np, int index, const char *name, - struct of_phandle_args *out_args); -struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec); +struct clk_hw *of_clk_get_hw(struct device_node *np, + int index, const char *con_id); +#else /* !CONFIG_COMMON_CLK || !CONFIG_OF */ +static inline struct clk_hw *of_clk_get_hw(struct device_node *np, + int index, const char *con_id) +{ + return ERR_PTR(-ENOENT); +} #endif #ifdef CONFIG_COMMON_CLK diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index f2f4f2afd28c..d3758bf4305c 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -27,66 +27,6 @@ static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); -#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) -static struct clk_hw *of_clk_get_hw(struct device_node *np, - int index, const char *con_id) -{ - int ret; - struct clk_hw *hw; - struct of_phandle_args clkspec; - - ret = of_parse_clkspec(np, index, con_id, &clkspec); - if (ret) - return ERR_PTR(ret); - - hw = of_clk_get_hw_from_clkspec(&clkspec); - of_node_put(clkspec.np); - - return hw; -} - -static struct clk *__of_clk_get(struct device_node *np, - int index, const char *dev_id, - const char *con_id) -{ - struct clk_hw *hw = of_clk_get_hw(np, index, con_id); - - return clk_hw_create_clk(NULL, hw, dev_id, con_id); -} - -struct clk *of_clk_get(struct device_node *np, int index) -{ - return __of_clk_get(np, index, np->full_name, NULL); -} -EXPORT_SYMBOL(of_clk_get); - -/** - * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node - * @np: pointer to clock consumer node - * @name: name of consumer's clock input, or NULL for the first clock reference - * - * This function parses the clocks and clock-names properties, - * and uses them to look up the struct clk from the registered list of clock - * providers. - */ -struct clk *of_clk_get_by_name(struct device_node *np, const char *name) -{ - if (!np) - return ERR_PTR(-ENOENT); - - return __of_clk_get(np, -1, np->full_name, name); -} -EXPORT_SYMBOL(of_clk_get_by_name); - -#else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */ - -static struct clk_hw *of_clk_get_hw(struct device_node *np, - int index, const char *con_id) -{ - return ERR_PTR(-ENOENT); -} -#endif - /* * Find the correct struct clk for the device and connection ID. * We do slightly fuzzy matching here: From patchwork Tue Jan 29 06:10:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 10785489 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D247291E for ; Tue, 29 Jan 2019 06:10:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C28062B62B for ; Tue, 29 Jan 2019 06:10:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B6CB92B630; Tue, 29 Jan 2019 06:10:29 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 B3C902B4A4 for ; Tue, 29 Jan 2019 06:10:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727536AbfA2GK1 (ORCPT ); Tue, 29 Jan 2019 01:10:27 -0500 Received: from mail.kernel.org ([198.145.29.99]:33472 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726217AbfA2GK0 (ORCPT ); Tue, 29 Jan 2019 01:10:26 -0500 Received: from mail.kernel.org (unknown [104.132.0.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 0DD4221871; Tue, 29 Jan 2019 06:10:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1548742225; bh=SZBnj1t2dRV/FqvdonmsGpWxhBu6FRdkm/W769WyMGI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=zeJbDXuhHg014VNet4Jn5wgwVhIPUnNWnBzHEBugDYxJI0IlhTDytHYpjY+vZM1fU UBjmRXCE5+/v0EahDmldSGP/7vCbIlqe6ZYSMHztE3n4p21glC7dWaJLK43RFb2rHR iwICLrRkdw4P67Iho6EtbBXpLV9RbfbzalsO9aDg= From: Stephen Boyd To: Michael Turquette , Stephen Boyd Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Miquel Raynal , Jerome Brunet , Russell King Subject: [PATCH 7/9] clk: Allow parents to be specified without string names Date: Mon, 28 Jan 2019 22:10:19 -0800 Message-Id: <20190129061021.94775-8-sboyd@kernel.org> X-Mailer: git-send-email 2.20.1.495.gaa96b0ce6b-goog In-Reply-To: <20190129061021.94775-1-sboyd@kernel.org> References: <20190129061021.94775-1-sboyd@kernel.org> MIME-Version: 1.0 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 common clk framework is lacking in ability to describe the clk topology without specifying strings for every possible parent-child link. There are a few drawbacks to the current approach: 1) String comparisons are used for everything, including describing topologies that are 'local' to a single clock controller. 2) clk providers (e.g. i2c clk drivers) need to create globally unique clk names to avoid collisions in the clk namespace, leading to awkward name generation code in various clk drivers. 3) DT bindings may not fully describe the clk topology and linkages between clk controllers because drivers can easily rely on globally unique strings to describe connections between clks. This leads to confusing DT bindings, complicated clk name generation code, and inefficient string comparisons during clk registration just so that the clk framework can detect the topology of the clk tree. Furthermore, some drivers call clk_get() and then __clk_get_name() to extract the globally unique clk name just so they can specify the parent of the clk they're registering. We have of_clk_parent_fill() but that mostly only works for single clks registered from a DT node, which isn't the norm. Let's simplify this all by introducing two new ways of specifying clk parents. The first method is an array of pointers to clk_hw structures corresponding to the parents at that index. This works for clks that are registered when we have access to all the clk_hw pointers for the parents. The second method is a mix of clk_hw pointers and strings of local and global parent clk names. If the .name member of the map is set we'll look for that clk by performing a DT based lookup of the device the clk is registered with and the .name specified in the map. If that fails, we'll fallback to the .fallback member and perform a global clk name lookup like we've always done before. Using either one of these new methods is entirely optional. Existing drivers will continue to work, and they can migrate to this new approach as they see fit. Eventually, we'll want to get rid of the 'parent_names' array in struct clk_init_data and use one of these new methods instead. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 215 +++++++++++++++++++++++++---------- include/linux/clk-provider.h | 17 ++- 2 files changed, 173 insertions(+), 59 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 202902e64799..0cd90a2339ad 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -42,6 +42,13 @@ static LIST_HEAD(clk_notifier_list); /*** private data structures ***/ +struct clk_parent_map { + struct clk_hw *hw; + struct clk_core *core; + const char *name; + const char *fallback; +}; + struct clk_core { const char *name; const struct clk_ops *ops; @@ -49,8 +56,7 @@ struct clk_core { struct module *owner; struct device *dev; struct clk_core *parent; - const char **parent_names; - struct clk_core **parents; + struct clk_parent_map *parents; u8 num_parents; u8 new_parent_index; unsigned long rate; @@ -319,17 +325,77 @@ static struct clk_core *clk_core_lookup(const char *name) return NULL; } +/** + * clk_core_get - Find the parent of a clk using a clock specifier in DT + * @core: clk to find parent of + * @name: name to search for in 'clock-names' of device providing clk + * + * This is the preferred method for clk providers to find the parent of a + * clk when that parent is external to the clk controller. The parent_names + * array is indexed and treated as a local name matching a string in the device + * node's 'clock-names' property. This allows clk providers to use their own + * namespace instead of looking for a globally unique parent string. + * + * For example the following DT snippet would allow a clock registered by the + * clock-controller@c001 that has a clk_init_data::parent_data array + * with 'xtal' in the 'name' member to find the clock provided by the + * clock-controller@f00abcd without needing to get the globally unique name of + * the xtal clk. + * + * parent: clock-controller@f00abcd { + * reg = <0xf00abcd 0xabcd>; + * #clock-cells = <0>; + * }; + * + * clock-controller@c001 { + * reg = <0xc001 0xf00d>; + * clocks = <&parent>; + * clock-names = "xtal"; + * #clock-cells = <1>; + * }; + */ +static struct clk_core *clk_core_get(struct clk_core *core, const char *name) +{ + struct clk_hw *hw; + struct device *dev = core->dev; + + if (!dev) + return NULL; + + /* TODO: Support clkdev clk_lookups */ + hw = of_clk_get_hw(dev->of_node, -1, name); + if (IS_ERR_OR_NULL(hw)) + return NULL; + + return hw->core; +} + +static void clk_core_fill_parent_index(struct clk_core *core, u8 index) +{ + struct clk_parent_map *entry = &core->parents[index]; + struct clk_core *parent = NULL; + + if (entry->hw) + parent = entry->hw->core; + else if (entry->name) + parent = clk_core_get(core, entry->name); + + if (!parent) + parent = clk_core_lookup(entry->fallback); + + entry->core = parent; +} + static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core, u8 index) { - if (!core || index >= core->num_parents) + if (!core || index >= core->num_parents || !core->parents) return NULL; - if (!core->parents[index]) - core->parents[index] = - clk_core_lookup(core->parent_names[index]); + if (!core->parents[index].core) + clk_core_fill_parent_index(core, index); - return core->parents[index]; + return core->parents[index].core; } struct clk_hw * @@ -2353,6 +2419,7 @@ void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent) bool clk_has_parent(struct clk *clk, struct clk *parent) { struct clk_core *core, *parent_core; + int i; /* NULL clocks should be nops, so return success if either is NULL. */ if (!clk || !parent) @@ -2365,8 +2432,11 @@ bool clk_has_parent(struct clk *clk, struct clk *parent) if (core->parent == parent_core) return true; - return match_string(core->parent_names, core->num_parents, - parent_core->name) >= 0; + for (i = 0; i < core->num_parents; i++) + if (!strcmp(core->parents[i].fallback, parent_core->name)) + return true; + + return false; } EXPORT_SYMBOL_GPL(clk_has_parent); @@ -2949,9 +3019,9 @@ static int possible_parents_show(struct seq_file *s, void *data) int i; for (i = 0; i < core->num_parents - 1; i++) - seq_printf(s, "%s ", core->parent_names[i]); + seq_printf(s, "%s ", core->parents[i].fallback); - seq_printf(s, "%s\n", core->parent_names[i]); + seq_printf(s, "%s\n", core->parents[i].fallback); return 0; } @@ -3085,7 +3155,7 @@ static inline void clk_debug_unregister(struct clk_core *core) */ static int __clk_core_init(struct clk_core *core) { - int i, ret; + int ret; struct clk_core *orphan; struct hlist_node *tmp2; unsigned long rate; @@ -3139,12 +3209,6 @@ static int __clk_core_init(struct clk_core *core) goto out; } - /* throw a WARN if any entries in parent_names are NULL */ - for (i = 0; i < core->num_parents; i++) - WARN(!core->parent_names[i], - "%s: invalid NULL in %s's .parent_names\n", - __func__, core->name); - ret = clk_init_parent(core); if (ret) goto out; @@ -3360,6 +3424,74 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw, return clk; } +static int clk_core_populate_parent_map(struct clk_core *core) +{ + const struct clk_init_data *init = core->hw->init; + u8 num_parents = init->num_parents; + const char * const *parent_names = init->parent_names; + struct clk_hw **parent_hws = init->parent_hws; + const struct clk_parent_data *parent_data = init->parent_data; + int i, ret = 0; + struct clk_parent_map *parents, *parent; + + if (!num_parents) + return 0; + + /* + * Avoid unnecessary string look-ups of clk_core's possible parents by + * having a cache of names/clk_hw pointers to clk_core pointers. + */ + parents = kcalloc(num_parents, sizeof(*parents), GFP_KERNEL); + core->parents = parents; + if (!parents) + return -ENOMEM; + + /* Copy everything over because it might be __initdata */ + for (i = 0, parent = parents; i < num_parents; i++, parent++) { + if (parent_names) { + /* throw a WARN if any entries are NULL */ + WARN(!parent_names[i], + "%s: invalid NULL in %s's .parent_names\n", + __func__, core->name); + parent->fallback = kstrdup_const(parent_names[i], + GFP_KERNEL); + if (!parent->fallback) { + ret = -ENOMEM; + while (--i >= 0) + kfree_const(parents[i].fallback); + } + } else if (parent_data) { + parent->hw = parent_data[i].hw; + parent->name = parent_data[i].name; + parent->fallback = parent_data[i].fallback; + } else if (parent_hws) { + parent->hw = parent_hws[i]; + } else { + ret = -EINVAL; + WARN(1, "Must specify parents if num_parents > 0\n"); + } + + if (ret) { + kfree(parents); + return ret; + } + } + + return 0; +} + +static void clk_core_free_parent_map(struct clk_core *core) +{ + int i = core->num_parents; + + if (!core->num_parents) + return; + + while (--i >= 0) + kfree_const(core->parents[i].fallback); + kfree(core->parents); +} + /** * clk_register - allocate a new clock, register it and return an opaque cookie * @dev: device that is registering this clock @@ -3373,7 +3505,7 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw, */ struct clk *clk_register(struct device *dev, struct clk_hw *hw) { - int i, ret; + int ret; struct clk_core *core; core = kzalloc(sizeof(*core), GFP_KERNEL); @@ -3406,33 +3538,9 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) core->max_rate = ULONG_MAX; hw->core = core; - /* allocate local copy in case parent_names is __initdata */ - core->parent_names = kcalloc(core->num_parents, sizeof(char *), - GFP_KERNEL); - - if (!core->parent_names) { - ret = -ENOMEM; - goto fail_parent_names; - } - - - /* copy each string name in case parent_names is __initdata */ - for (i = 0; i < core->num_parents; i++) { - core->parent_names[i] = kstrdup_const(hw->init->parent_names[i], - GFP_KERNEL); - if (!core->parent_names[i]) { - ret = -ENOMEM; - goto fail_parent_names_copy; - } - } - - /* avoid unnecessary string look-ups of clk_core's possible parents. */ - core->parents = kcalloc(core->num_parents, sizeof(*core->parents), - GFP_KERNEL); - if (!core->parents) { - ret = -ENOMEM; + ret = clk_core_populate_parent_map(core); + if (ret) goto fail_parents; - }; INIT_HLIST_HEAD(&core->clks); @@ -3443,7 +3551,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) hw->clk = alloc_clk(core, NULL, NULL); if (IS_ERR(hw->clk)) { ret = PTR_ERR(hw->clk); - goto fail_parents; + goto fail_create_clk; } clk_core_link_consumer(hw->core, hw->clk); @@ -3459,13 +3567,9 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) free_clk(hw->clk); hw->clk = NULL; +fail_create_clk: + clk_core_free_parent_map(core); fail_parents: - kfree(core->parents); -fail_parent_names_copy: - while (--i >= 0) - kfree_const(core->parent_names[i]); - kfree(core->parent_names); -fail_parent_names: fail_ops: kfree_const(core->name); fail_name: @@ -3495,15 +3599,10 @@ EXPORT_SYMBOL_GPL(clk_hw_register); static void __clk_release(struct kref *ref) { struct clk_core *core = container_of(ref, struct clk_core, ref); - int i = core->num_parents; lockdep_assert_held(&prepare_lock); - kfree(core->parents); - while (--i >= 0) - kfree_const(core->parent_names[i]); - - kfree(core->parent_names); + clk_core_free_parent_map(core); kfree_const(core->name); kfree(core); } diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 8b84dee942bf..f513f4074a93 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -264,6 +264,18 @@ struct clk_ops { void (*debug_init)(struct clk_hw *hw, struct dentry *dentry); }; +/** + * struct clk_parent_data - clk parent information + * @hw: parent clk_hw pointer (used for clk providers with internal clks) + * @name: parent name local to provider registering clk + * @fallback: globally unique parent name (used as a fallback) + */ +struct clk_parent_data { + struct clk_hw *hw; + const char *name; + const char *fallback; +}; + /** * struct clk_init_data - holds init data that's common to all clocks and is * shared between the clock provider and the common clock framework. @@ -277,7 +289,10 @@ struct clk_ops { struct clk_init_data { const char *name; const struct clk_ops *ops; - const char * const *parent_names; + /* Only one of the following three should be assigned */ + const char * const *parent_names; /* If NULL (and num_parents != 0) look at parent_data and parent_hws */ + const struct clk_parent_data *parent_data; + struct clk_hw **parent_hws; u8 num_parents; unsigned long flags; }; From patchwork Tue Jan 29 06:10:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 10785491 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0E7491874 for ; Tue, 29 Jan 2019 06:10:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F3EFD2B630 for ; Tue, 29 Jan 2019 06:10:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F128B2B62D; Tue, 29 Jan 2019 06:10:29 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 168392B4BB for ; Tue, 29 Jan 2019 06:10:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727580AbfA2GK1 (ORCPT ); Tue, 29 Jan 2019 01:10:27 -0500 Received: from mail.kernel.org ([198.145.29.99]:33484 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727444AbfA2GK1 (ORCPT ); Tue, 29 Jan 2019 01:10:27 -0500 Received: from mail.kernel.org (unknown [104.132.0.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 6E12021873; Tue, 29 Jan 2019 06:10:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1548742225; bh=8OWpSkUy4dPTB7G6tQ9SurVjPpM690XiBZ84Y9OR6w8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=muTgoQHowEnKiFGG6ylcj22+mZq+vGuj9K7fSfc2u5xYy2jcVfpGhp6NJqNZGSxdT 7SuZp/uE3Px0Mw+kBYK93yUDWQtvyUG6YQyHm1ioBpH4+mxrZbwTjlYKu61O+HPIU7 NFUrAIVVmS4MdjPJETWNBy4Uen5hRiMK3ROibhSc= From: Stephen Boyd To: Michael Turquette , Stephen Boyd Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Miquel Raynal , Jerome Brunet , Russell King Subject: [PATCH 8/9] clk: qcom: gcc-sdm845: Migrate to DT parent mapping Date: Mon, 28 Jan 2019 22:10:20 -0800 Message-Id: <20190129061021.94775-9-sboyd@kernel.org> X-Mailer: git-send-email 2.20.1.495.gaa96b0ce6b-goog In-Reply-To: <20190129061021.94775-1-sboyd@kernel.org> References: <20190129061021.94775-1-sboyd@kernel.org> MIME-Version: 1.0 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 TODO: Fully convert driver Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sdm845.c | 180 +++++++++++++++++----------------- 1 file changed, 89 insertions(+), 91 deletions(-) diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c index f133b7f5652f..9da9a337238d 100644 --- a/drivers/clk/qcom/gcc-sdm845.c +++ b/drivers/clk/qcom/gcc-sdm845.c @@ -25,6 +25,59 @@ #include "gdsc.h" #include "reset.h" +static struct clk_alpha_pll gpll0 = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpll0", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_fabia_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll4 = { + .offset = 0x76000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gpll4", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_fabia_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_fabia_even[] = { + { 0x0, 1 }, + { 0x1, 2 }, + { 0x3, 4 }, + { 0x7, 8 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll0_out_even = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_fabia_even, + .num_post_div = ARRAY_SIZE(post_div_table_fabia_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll0_out_even", + .parent_names = (const char *[]){ "gpll0" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_fabia_ops, + }, +}; + enum { P_BI_TCXO, P_AUD_REF_CLK, @@ -42,11 +95,11 @@ static const struct parent_map gcc_parent_map_0[] = { { P_CORE_BI_PLL_TEST_SE, 7 }, }; -static const char * const gcc_parent_names_0[] = { - "bi_tcxo", - "gpll0", - "gpll0_out_even", - "core_bi_pll_test_se", +static const struct clk_parent_data gcc_parent_data_0[] = { + { .name = "xo", .fallback = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, + { .name = "core_bi_pll_test_se", .fallback = "core_bi_pll_test_se" } }; static const struct parent_map gcc_parent_map_1[] = { @@ -144,59 +197,6 @@ static const char * const gcc_parent_names_10[] = { "core_bi_pll_test_se", }; -static struct clk_alpha_pll gpll0 = { - .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], - .clkr = { - .enable_reg = 0x52000, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gpll0", - .parent_names = (const char *[]){ "bi_tcxo" }, - .num_parents = 1, - .ops = &clk_alpha_pll_fixed_fabia_ops, - }, - }, -}; - -static struct clk_alpha_pll gpll4 = { - .offset = 0x76000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], - .clkr = { - .enable_reg = 0x52000, - .enable_mask = BIT(4), - .hw.init = &(struct clk_init_data){ - .name = "gpll4", - .parent_names = (const char *[]){ "bi_tcxo" }, - .num_parents = 1, - .ops = &clk_alpha_pll_fixed_fabia_ops, - }, - }, -}; - -static const struct clk_div_table post_div_table_fabia_even[] = { - { 0x0, 1 }, - { 0x1, 2 }, - { 0x3, 4 }, - { 0x7, 8 }, - { } -}; - -static struct clk_alpha_pll_postdiv gpll0_out_even = { - .offset = 0x0, - .post_div_shift = 8, - .post_div_table = post_div_table_fabia_even, - .num_post_div = ARRAY_SIZE(post_div_table_fabia_even), - .width = 4, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], - .clkr.hw.init = &(struct clk_init_data){ - .name = "gpll0_out_even", - .parent_names = (const char *[]){ "gpll0" }, - .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_fabia_ops, - }, -}; - static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = { F(19200000, P_BI_TCXO, 1, 0, 0), { } @@ -334,7 +334,7 @@ static struct clk_rcg2 gcc_pcie_phy_refgen_clk_src = { .freq_tbl = ftbl_gcc_pcie_phy_refgen_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_pcie_phy_refgen_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_ops, }, @@ -356,7 +356,7 @@ static struct clk_rcg2 gcc_qspi_core_clk_src = { .freq_tbl = ftbl_gcc_qspi_core_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_qspi_core_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_floor_ops, }, @@ -377,7 +377,7 @@ static struct clk_rcg2 gcc_pdm2_clk_src = { .freq_tbl = ftbl_gcc_pdm2_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_pdm2_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_ops, }, @@ -404,7 +404,7 @@ static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { static struct clk_init_data gcc_qupv3_wrap0_s0_clk_init = { .name = "gcc_qupv3_wrap0_s0_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -420,7 +420,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { static struct clk_init_data gcc_qupv3_wrap0_s1_clk_init = { .name = "gcc_qupv3_wrap0_s1_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -436,7 +436,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { static struct clk_init_data gcc_qupv3_wrap0_s2_clk_init = { .name = "gcc_qupv3_wrap0_s2_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -452,7 +452,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { static struct clk_init_data gcc_qupv3_wrap0_s3_clk_init = { .name = "gcc_qupv3_wrap0_s3_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -468,7 +468,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { static struct clk_init_data gcc_qupv3_wrap0_s4_clk_init = { .name = "gcc_qupv3_wrap0_s4_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -484,7 +484,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { static struct clk_init_data gcc_qupv3_wrap0_s5_clk_init = { .name = "gcc_qupv3_wrap0_s5_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -500,7 +500,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { static struct clk_init_data gcc_qupv3_wrap0_s6_clk_init = { .name = "gcc_qupv3_wrap0_s6_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -516,7 +516,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s6_clk_src = { static struct clk_init_data gcc_qupv3_wrap0_s7_clk_init = { .name = "gcc_qupv3_wrap0_s7_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -532,7 +532,7 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s7_clk_src = { static struct clk_init_data gcc_qupv3_wrap1_s0_clk_init = { .name = "gcc_qupv3_wrap1_s0_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -548,7 +548,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = { static struct clk_init_data gcc_qupv3_wrap1_s1_clk_init = { .name = "gcc_qupv3_wrap1_s1_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -564,7 +564,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = { static struct clk_init_data gcc_qupv3_wrap1_s2_clk_init = { .name = "gcc_qupv3_wrap1_s2_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -580,7 +580,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = { static struct clk_init_data gcc_qupv3_wrap1_s3_clk_init = { .name = "gcc_qupv3_wrap1_s3_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -596,7 +596,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = { static struct clk_init_data gcc_qupv3_wrap1_s4_clk_init = { .name = "gcc_qupv3_wrap1_s4_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -612,7 +612,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = { static struct clk_init_data gcc_qupv3_wrap1_s5_clk_init = { .name = "gcc_qupv3_wrap1_s5_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -628,7 +628,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = { static struct clk_init_data gcc_qupv3_wrap1_s6_clk_init = { .name = "gcc_qupv3_wrap1_s6_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -644,7 +644,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s6_clk_src = { static struct clk_init_data gcc_qupv3_wrap1_s7_clk_init = { .name = "gcc_qupv3_wrap1_s7_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }; @@ -701,7 +701,7 @@ static struct clk_rcg2 gcc_sdcc4_apps_clk_src = { .freq_tbl = ftbl_gcc_sdcc4_apps_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_sdcc4_apps_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_ops, }, @@ -743,7 +743,7 @@ static struct clk_rcg2 gcc_ufs_card_axi_clk_src = { .freq_tbl = ftbl_gcc_ufs_card_axi_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_ufs_card_axi_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }, @@ -765,7 +765,7 @@ static struct clk_rcg2 gcc_ufs_card_ice_core_clk_src = { .freq_tbl = ftbl_gcc_ufs_card_ice_core_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_ufs_card_ice_core_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }, @@ -800,7 +800,7 @@ static struct clk_rcg2 gcc_ufs_card_unipro_core_clk_src = { .freq_tbl = ftbl_gcc_ufs_card_unipro_core_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_ufs_card_unipro_core_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }, @@ -823,7 +823,7 @@ static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = { .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_ufs_phy_axi_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }, @@ -837,7 +837,7 @@ static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = { .freq_tbl = ftbl_gcc_ufs_card_ice_core_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_ufs_phy_ice_core_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }, @@ -865,7 +865,7 @@ static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = { .freq_tbl = ftbl_gcc_ufs_card_unipro_core_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_ufs_phy_unipro_core_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }, @@ -888,7 +888,7 @@ static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_usb30_prim_master_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }, @@ -910,7 +910,7 @@ static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_usb30_prim_mock_utmi_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_shared_ops, }, @@ -924,7 +924,7 @@ static struct clk_rcg2 gcc_usb30_sec_master_clk_src = { .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_usb30_sec_master_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_ops, }, @@ -938,7 +938,7 @@ static struct clk_rcg2 gcc_usb30_sec_mock_utmi_clk_src = { .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_usb30_sec_mock_utmi_clk_src", - .parent_names = gcc_parent_names_0, + .parent_data = gcc_parent_data_0, .num_parents = 4, .ops = &clk_rcg2_ops, }, @@ -1030,9 +1030,7 @@ static struct clk_branch gcc_aggre_ufs_card_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_aggre_ufs_card_axi_clk", - .parent_names = (const char *[]){ - "gcc_ufs_card_axi_clk_src", - }, + .parent_hws = (struct clk_hw *[]){ &gcc_ufs_card_axi_clk_src.clkr.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, From patchwork Tue Jan 29 06:10:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 10785493 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 26BEB91E for ; Tue, 29 Jan 2019 06:10:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1806A2B63B for ; Tue, 29 Jan 2019 06:10:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0C9152B663; Tue, 29 Jan 2019 06:10:50 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 B46F52B63B for ; Tue, 29 Jan 2019 06:10:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726276AbfA2GKn (ORCPT ); Tue, 29 Jan 2019 01:10:43 -0500 Received: from mail.kernel.org ([198.145.29.99]:33440 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727476AbfA2GK0 (ORCPT ); Tue, 29 Jan 2019 01:10:26 -0500 Received: from mail.kernel.org (unknown [104.132.0.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id C7C0321874; Tue, 29 Jan 2019 06:10:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1548742226; bh=fmSRU4c+3VYxyHTO+gXsJNTOFI+9uoGhMdrxeyAoZsI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=APN81oJi/xQ1YdfJsr4jlz+OONKN+ClQZUc1zP6/LyT3oCf3kG679uOEttJZAJgou 8U59tHv6Qbgzuc3WO5uNROYFEdQIamanhPmszmQw4rJ/k25NkjVomX8BsTv/KGbrgj WfLAKIqZtQnnskv0LW5bhH+k0Fm8vWckPiS28T4c= From: Stephen Boyd To: Michael Turquette , Stephen Boyd Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Miquel Raynal , Jerome Brunet , Russell King Subject: [PATCH 9/9] arm64: dts: qcom: Specify XO clk as input to GCC node Date: Mon, 28 Jan 2019 22:10:21 -0800 Message-Id: <20190129061021.94775-10-sboyd@kernel.org> X-Mailer: git-send-email 2.20.1.495.gaa96b0ce6b-goog In-Reply-To: <20190129061021.94775-1-sboyd@kernel.org> References: <20190129061021.94775-1-sboyd@kernel.org> MIME-Version: 1.0 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 This is an example patch to show how DT nodes are updated to specify the clocks which are external to the clock controller can be specified in DT and then found by the clk core to do parent-child linkage. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index b72bdb0a31a5..46e0b467b411 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -338,6 +338,8 @@ #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; }; qfprom@784000 {