aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/clkdev.c
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2012-04-09 15:50:06 -0400
committerMike Turquette <mturquette@linaro.org>2012-07-11 20:58:45 -0400
commit766e6a4ec602d0c107553b91b3434fe9c03474f4 (patch)
treeaa9bbba36954d927e931cc50c6a28ef9cced571c /drivers/clk/clkdev.c
parenta613163dff04cbfcb7d66b06ef4a5f65498ee59b (diff)
clk: add DT clock binding support
Based on work 1st by Ben Herrenschmidt and Jeremy Kerr, then by Grant Likely, this patch adds support to clk_get to allow drivers to retrieve clock data from the device tree. Platforms scan for clocks in DT with of_clk_init and a match table, and the register a provider through of_clk_add_provider. The provider's clk_src_get function will be called when a device references the provider's OF node for a clock reference. v6 (Rob Herring): - Return error values instead of NULL to match clock framework expectations v5 (Rob Herring): - Move from drivers/of into common clock subsystem - Squashed "dt/clock: add a simple provider get function" and "dt/clock: add function to get parent clock name" - Rebase to 3.4-rc1 - Drop CONFIG_OF_CLOCK and just use CONFIG_OF - Add missing EXPORT_SYMBOL to various functions - s/clock-output-name/clock-output-names/ - Define that fixed-clock binding is a single output v4 (Rob Herring): - Rework for common clk subsystem - Add of_clk_get_parent_name function v3: - Clarified documentation v2: - fixed errant ';' causing compile error - Editorial fixes from Shawn Guo - merged in adding lookup to clkdev - changed property names to match established convention. After working with the binding a bit it really made more sense to follow the lead of 'reg', 'gpios' and 'interrupts' by making the input simply 'clocks' & 'clock-names' instead of 'clock-input-*', and to only use clock-output* for the producer nodes. (Sorry Shawn, this will mean you need to change some code, but it should be trivial) - Add ability to inherit clocks from parent nodes by using an empty 'clock-ranges' property. Useful for busses. I could use some feedback on the new property name, 'clock-ranges' doesn't feel right to me. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Rob Herring <rob.herring@calxeda.com> Reviewed-by: Shawn Guo <shawn.guo@freescale.com> Cc: Sascha Hauer <kernel@pengutronix.de> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/clkdev.c')
-rw-r--r--drivers/clk/clkdev.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index c535cf8c5770..20649b3c88fe 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -19,10 +19,80 @@
19#include <linux/mutex.h> 19#include <linux/mutex.h>
20#include <linux/clk.h> 20#include <linux/clk.h>
21#include <linux/clkdev.h> 21#include <linux/clkdev.h>
22#include <linux/of.h>
22 23
23static LIST_HEAD(clocks); 24static LIST_HEAD(clocks);
24static DEFINE_MUTEX(clocks_mutex); 25static DEFINE_MUTEX(clocks_mutex);
25 26
27#ifdef CONFIG_OF
28struct clk *of_clk_get(struct device_node *np, int index)
29{
30 struct of_phandle_args clkspec;
31 struct clk *clk;
32 int rc;
33
34 if (index < 0)
35 return ERR_PTR(-EINVAL);
36
37 rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
38 &clkspec);
39 if (rc)
40 return ERR_PTR(rc);
41
42 clk = of_clk_get_from_provider(&clkspec);
43 of_node_put(clkspec.np);
44 return clk;
45}
46EXPORT_SYMBOL(of_clk_get);
47
48/**
49 * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
50 * @np: pointer to clock consumer node
51 * @name: name of consumer's clock input, or NULL for the first clock reference
52 *
53 * This function parses the clocks and clock-names properties,
54 * and uses them to look up the struct clk from the registered list of clock
55 * providers.
56 */
57struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
58{
59 struct clk *clk = ERR_PTR(-ENOENT);
60
61 /* Walk up the tree of devices looking for a clock that matches */
62 while (np) {
63 int index = 0;
64
65 /*
66 * For named clocks, first look up the name in the
67 * "clock-names" property. If it cannot be found, then
68 * index will be an error code, and of_clk_get() will fail.
69 */
70 if (name)
71 index = of_property_match_string(np, "clock-names", name);
72 clk = of_clk_get(np, index);
73 if (!IS_ERR(clk))
74 break;
75 else if (name && index >= 0) {
76 pr_err("ERROR: could not get clock %s:%s(%i)\n",
77 np->full_name, name ? name : "", index);
78 return clk;
79 }
80
81 /*
82 * No matching clock found on this node. If the parent node
83 * has a "clock-ranges" property, then we can try one of its
84 * clocks.
85 */
86 np = np->parent;
87 if (np && !of_get_property(np, "clock-ranges", NULL))
88 break;
89 }
90
91 return clk;
92}
93EXPORT_SYMBOL(of_clk_get_by_name);
94#endif
95
26/* 96/*
27 * Find the correct struct clk for the device and connection ID. 97 * Find the correct struct clk for the device and connection ID.
28 * We do slightly fuzzy matching here: 98 * We do slightly fuzzy matching here:
@@ -83,6 +153,13 @@ EXPORT_SYMBOL(clk_get_sys);
83struct clk *clk_get(struct device *dev, const char *con_id) 153struct clk *clk_get(struct device *dev, const char *con_id)
84{ 154{
85 const char *dev_id = dev ? dev_name(dev) : NULL; 155 const char *dev_id = dev ? dev_name(dev) : NULL;
156 struct clk *clk;
157
158 if (dev) {
159 clk = of_clk_get_by_name(dev->of_node, con_id);
160 if (clk && __clk_get(clk))
161 return clk;
162 }
86 163
87 return clk_get_sys(dev_id, con_id); 164 return clk_get_sys(dev_id, con_id);
88} 165}