From patchwork Mon Dec 17 21:02:12 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 1888961 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id AD0133FCA5 for ; Mon, 17 Dec 2012 21:05:52 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TkhpX-0002av-E0; Mon, 17 Dec 2012 21:02:31 +0000 Received: from wolverine01.qualcomm.com ([199.106.114.254]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TkhpN-0002ZF-6t for linux-arm-kernel@lists.infradead.org; Mon, 17 Dec 2012 21:02:22 +0000 X-IronPort-AV: E=Sophos;i="4.84,304,1355126400"; d="scan'208";a="14662749" Received: from pdmz-ns-snip_115_219.qualcomm.com (HELO mostmsg01.qualcomm.com) ([199.106.115.219]) by wolverine01.qualcomm.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 17 Dec 2012 13:02:18 -0800 Received: from sboyd-linux.qualcomm.com (pdmz-ns-snip_218_1.qualcomm.com [192.168.218.1]) by mostmsg01.qualcomm.com (Postfix) with ESMTPA id 77F6410004D7; Mon, 17 Dec 2012 13:02:18 -0800 (PST) From: Stephen Boyd To: Mike Turquette Subject: [PATCH 1/4] clk: Add of_init_clk_data() to parse common clock bindings Date: Mon, 17 Dec 2012 13:02:12 -0800 Message-Id: <1355778135-32458-2-git-send-email-sboyd@codeaurora.org> X-Mailer: git-send-email 1.8.1.rc1 In-Reply-To: <1355778135-32458-1-git-send-email-sboyd@codeaurora.org> References: <1355778135-32458-1-git-send-email-sboyd@codeaurora.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121217_160221_490153_FE990B11 X-CRM114-Status: GOOD ( 20.83 ) X-Spam-Score: -4.2 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [199.106.114.254 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Rob Herring , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Consolidate DT parsing for the common bits of a clock binding in one place to simplify clock drivers. This also has the added benefit of standardizing how the clock names used by the common clock framework are generated from the DT bindings. We always use the first clock-output-names string if it exists, otherwise we fall back to the node name. To be slightly more efficient and make the caller's life easier, we introduce a shallow copy flag so that the clock core knows to just copy the pointers to the strings and not the string contents. Otherwise the callers of this function would have to free the strings allocated here which could be cumbersome. Signed-off-by: Stephen Boyd Cc: Rob Herring --- drivers/clk/clk.c | 58 +++++++++++++++++++++++++++++++++++++++++++- include/linux/clk-provider.h | 2 ++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 251e45d..95380a9 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1383,6 +1383,10 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) { int i, ret; + hw->clk = clk; + if (hw->init->flags & CLK_SHALLOW_COPY) + return PTR_RET(__clk_register(dev, hw)); + clk->name = kstrdup(hw->init->name, GFP_KERNEL); if (!clk->name) { pr_err("%s: could not allocate clk->name\n", __func__); @@ -1393,7 +1397,6 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) clk->hw = hw; clk->flags = hw->init->flags; clk->num_parents = hw->init->num_parents; - hw->clk = clk; /* allocate local copy in case parent_names is __initdata */ clk->parent_names = kzalloc((sizeof(char*) * clk->num_parents), @@ -1797,4 +1800,57 @@ void __init of_clk_init(const struct of_device_id *matches) clk_init_cb(np); } } + +/** + * of_init_clk_data() - Initialize a clk_init_data struct from a DT node + * @np: node to initialize struct from + * @init: struct to initialize + * + * Populates the clk_init_data struct by parsing the device node for + * properties matching the common clock binding. Returns 0 on success + * and a negative error code on failure. + */ +int of_init_clk_data(struct device_node *np, struct clk_init_data *init) +{ + struct of_phandle_args s; + const char **names = NULL, **p; + const char *name; + int i; + + if (of_property_read_string(np, "clock-output-names", &name) < 0) + name = np->name; + init->name = kstrdup(name, GFP_KERNEL); + if (!init->name) + return -ENOMEM; + + for (i = 0; of_parse_phandle_with_args(np, "clocks", "#clock-cells", + i, &s) == 0; i++) { + p = krealloc(names, sizeof(*names) * (i + 1), GFP_KERNEL); + if (!p) + goto err; + names = p; + + if (of_property_read_string(s.np, "clock-output-names", + &name) < 0) + name = s.np->name; + names[i] = kstrdup(name, GFP_KERNEL); + if (!names[i]) + goto err; + of_node_put(s.np); + } + + init->parent_names = names; + init->num_parents = i; + init->flags = CLK_SHALLOW_COPY; + + return 0; +err: + of_node_put(s.np); + while (--i >= 0) + kfree(names[i]); + kfree(names); + kfree(init->name); + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(of_init_clk_data); #endif diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 4989b8a..9d3db2b 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -27,6 +27,7 @@ #define CLK_IS_ROOT BIT(4) /* root clk, has no parent */ #define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */ #define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ +#define CLK_SHALLOW_COPY BIT(7) /* don't copy the initdata strings */ struct clk_hw; @@ -380,6 +381,7 @@ struct clk_onecell_data { struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data); const char *of_clk_get_parent_name(struct device_node *np, int index); void of_clk_init(const struct of_device_id *matches); +int of_init_clk_data(struct device_node *np, struct clk_init_data *init); #endif /* CONFIG_COMMON_CLK */ #endif /* CLK_PROVIDER_H */