diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2012-04-09 15:50:06 -0400 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2012-07-11 20:58:45 -0400 |
commit | 766e6a4ec602d0c107553b91b3434fe9c03474f4 (patch) | |
tree | aa9bbba36954d927e931cc50c6a28ef9cced571c /drivers/clk/clkdev.c | |
parent | a613163dff04cbfcb7d66b06ef4a5f65498ee59b (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.c | 77 |
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 | ||
23 | static LIST_HEAD(clocks); | 24 | static LIST_HEAD(clocks); |
24 | static DEFINE_MUTEX(clocks_mutex); | 25 | static DEFINE_MUTEX(clocks_mutex); |
25 | 26 | ||
27 | #ifdef CONFIG_OF | ||
28 | struct 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 | } | ||
46 | EXPORT_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 | */ | ||
57 | struct 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 | } | ||
93 | EXPORT_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); | |||
83 | struct clk *clk_get(struct device *dev, const char *con_id) | 153 | struct 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 | } |