From patchwork Thu Feb 13 09:00:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tero Kristo X-Patchwork-Id: 319918 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 1FCF22C00B5 for ; Thu, 13 Feb 2014 20:01:35 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753457AbaBMJBc (ORCPT ); Thu, 13 Feb 2014 04:01:32 -0500 Received: from arroyo.ext.ti.com ([192.94.94.40]:55186 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753423AbaBMJBb (ORCPT ); Thu, 13 Feb 2014 04:01:31 -0500 Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id s1D9169r013704; Thu, 13 Feb 2014 03:01:06 -0600 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id s1D9162N012591; Thu, 13 Feb 2014 03:01:06 -0600 Received: from dlep33.itg.ti.com (157.170.170.75) by DFLE72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.3.174.1; Thu, 13 Feb 2014 03:01:06 -0600 Received: from localhost.localdomain (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id s1D911bk021319; Thu, 13 Feb 2014 03:01:05 -0600 From: Tero Kristo To: , CC: , Subject: [PATCH 2/4] clk: add support for default-rate Date: Thu, 13 Feb 2014 11:00:46 +0200 Message-ID: <1392282048-6284-3-git-send-email-t-kristo@ti.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1392282048-6284-1-git-send-email-t-kristo@ti.com> References: <1392282048-6284-1-git-send-email-t-kristo@ti.com> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org default-rate property can now be used to set initial rates for clocks. This is added by default for all clocks which get initialized through of_clk_init(). Signed-off-by: Tero Kristo --- .../devicetree/bindings/clock/clock-bindings.txt | 9 ++ drivers/clk/clk.c | 86 ++++++++++++++++++++ include/linux/clk-provider.h | 2 + 3 files changed, 97 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt index 7c52c29..d676112 100644 --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt @@ -44,6 +44,15 @@ For example: clocks by index. The names should reflect the clock output signal names for the device. +default-rate: Sets the rate of the clock during boot to the provided + rate. + +For example: + + clk-divider { + default-rate = <1000000>; + }; + ==Clock consumers== Required properties: diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 5517944..cb144e4 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2526,6 +2526,89 @@ const char *of_clk_get_parent_name(struct device_node *np, int index) } EXPORT_SYMBOL_GPL(of_clk_get_parent_name); +static LIST_HEAD(clk_init_info_list); + +struct clk_init_info { + struct device_node *node; + struct clk *clk; + u32 rate; + struct list_head link; + struct list_head sort_link; +}; + +int __init of_clk_parse_init_rate(struct device_node *node, struct clk *clk) +{ + u32 rate; + struct clk_init_info *cinfo; + + if (of_property_read_u32(node, "default-rate", &rate)) + return 0; + + cinfo = kzalloc(sizeof(*cinfo), GFP_KERNEL); + if (!cinfo) + return -ENOMEM; + + cinfo->node = node; + cinfo->clk = clk; + cinfo->rate = rate; + list_add(&cinfo->link, &clk_init_info_list); + INIT_LIST_HEAD(&cinfo->sort_link); + + return 0; +} + +int __init of_clk_set_init_rates(void) +{ + struct clk_init_info *cinfo, *tmp; + struct of_phandle_args clkspec; + int ret = 0; + struct list_head sorted_list; + struct clk *clk; + + INIT_LIST_HEAD(&sorted_list); + + list_for_each_entry(cinfo, &clk_init_info_list, link) { + /* Get missing clk pointers */ + if (!cinfo->clk) { + clkspec.np = cinfo->node; + cinfo->clk = of_clk_get_from_provider(&clkspec); + } + + /* Check if we are the parent of any of the sorted clocks */ + list_for_each_entry(tmp, &sorted_list, sort_link) { + clk = tmp->clk; + while (clk && clk != cinfo->clk) + clk = clk->parent; + + if (clk == cinfo->clk) { + /* Add us before this node in the list */ + list_add_tail(&cinfo->sort_link, + &tmp->sort_link); + break; + } + } + + if (list_empty(&cinfo->sort_link)) + list_add_tail(&cinfo->sort_link, &sorted_list); + } + + /* Process sorted list and set clk rates */ + list_for_each_entry_safe(cinfo, tmp, &sorted_list, sort_link) { + int r = clk_set_rate(cinfo->clk, cinfo->rate); + if (r) { + pr_err("%s: clk_set_rate for %s failed: %d\n", __func__, + cinfo->node->name, ret); + ret = r; + } + + /* Clean up the static list */ + list_del(&cinfo->link); + kfree(cinfo); + } + + return ret; +} + /** * of_clk_init() - Scan and init clock providers from the DT * @matches: array of compatible values and init functions for providers. @@ -2544,6 +2627,9 @@ void __init of_clk_init(const struct of_device_id *matches) for_each_matching_node_and_match(np, matches, &match) { of_clk_init_cb_t clk_init_cb = match->data; clk_init_cb(np); + of_clk_parse_init_rate(np, NULL); } + + of_clk_set_init_rates(); } #endif diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 939533d..1bbd194 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -506,6 +506,8 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data); int of_clk_get_parent_count(struct device_node *np); const char *of_clk_get_parent_name(struct device_node *np, int index); +int of_clk_parse_init_rate(struct device_node *node, struct clk *clk); +int of_clk_set_init_rates(void); void of_clk_init(const struct of_device_id *matches);