diff options
Diffstat (limited to 'drivers/clk/clkdev.c')
-rw-r--r-- | drivers/clk/clkdev.c | 110 |
1 files changed, 76 insertions, 34 deletions
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index da4bda8b7fc7..043fd3633373 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c | |||
@@ -19,6 +19,7 @@ | |||
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/clk-provider.h> | ||
22 | #include <linux/of.h> | 23 | #include <linux/of.h> |
23 | 24 | ||
24 | #include "clk.h" | 25 | #include "clk.h" |
@@ -28,6 +29,20 @@ static DEFINE_MUTEX(clocks_mutex); | |||
28 | 29 | ||
29 | #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) | 30 | #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) |
30 | 31 | ||
32 | static struct clk *__of_clk_get_by_clkspec(struct of_phandle_args *clkspec, | ||
33 | const char *dev_id, const char *con_id) | ||
34 | { | ||
35 | struct clk *clk; | ||
36 | |||
37 | if (!clkspec) | ||
38 | return ERR_PTR(-EINVAL); | ||
39 | |||
40 | of_clk_lock(); | ||
41 | clk = __of_clk_get_from_provider(clkspec, dev_id, con_id); | ||
42 | of_clk_unlock(); | ||
43 | return clk; | ||
44 | } | ||
45 | |||
31 | /** | 46 | /** |
32 | * of_clk_get_by_clkspec() - Lookup a clock form a clock provider | 47 | * of_clk_get_by_clkspec() - Lookup a clock form a clock provider |
33 | * @clkspec: pointer to a clock specifier data structure | 48 | * @clkspec: pointer to a clock specifier data structure |
@@ -38,22 +53,11 @@ static DEFINE_MUTEX(clocks_mutex); | |||
38 | */ | 53 | */ |
39 | struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec) | 54 | struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec) |
40 | { | 55 | { |
41 | struct clk *clk; | 56 | return __of_clk_get_by_clkspec(clkspec, NULL, __func__); |
42 | |||
43 | if (!clkspec) | ||
44 | return ERR_PTR(-EINVAL); | ||
45 | |||
46 | of_clk_lock(); | ||
47 | clk = __of_clk_get_from_provider(clkspec); | ||
48 | |||
49 | if (!IS_ERR(clk) && !__clk_get(clk)) | ||
50 | clk = ERR_PTR(-ENOENT); | ||
51 | |||
52 | of_clk_unlock(); | ||
53 | return clk; | ||
54 | } | 57 | } |
55 | 58 | ||
56 | struct clk *of_clk_get(struct device_node *np, int index) | 59 | static struct clk *__of_clk_get(struct device_node *np, int index, |
60 | const char *dev_id, const char *con_id) | ||
57 | { | 61 | { |
58 | struct of_phandle_args clkspec; | 62 | struct of_phandle_args clkspec; |
59 | struct clk *clk; | 63 | struct clk *clk; |
@@ -67,22 +71,21 @@ struct clk *of_clk_get(struct device_node *np, int index) | |||
67 | if (rc) | 71 | if (rc) |
68 | return ERR_PTR(rc); | 72 | return ERR_PTR(rc); |
69 | 73 | ||
70 | clk = of_clk_get_by_clkspec(&clkspec); | 74 | clk = __of_clk_get_by_clkspec(&clkspec, dev_id, con_id); |
71 | of_node_put(clkspec.np); | 75 | of_node_put(clkspec.np); |
76 | |||
72 | return clk; | 77 | return clk; |
73 | } | 78 | } |
79 | |||
80 | struct clk *of_clk_get(struct device_node *np, int index) | ||
81 | { | ||
82 | return __of_clk_get(np, index, np->full_name, NULL); | ||
83 | } | ||
74 | EXPORT_SYMBOL(of_clk_get); | 84 | EXPORT_SYMBOL(of_clk_get); |
75 | 85 | ||
76 | /** | 86 | static struct clk *__of_clk_get_by_name(struct device_node *np, |
77 | * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node | 87 | const char *dev_id, |
78 | * @np: pointer to clock consumer node | 88 | const char *name) |
79 | * @name: name of consumer's clock input, or NULL for the first clock reference | ||
80 | * | ||
81 | * This function parses the clocks and clock-names properties, | ||
82 | * and uses them to look up the struct clk from the registered list of clock | ||
83 | * providers. | ||
84 | */ | ||
85 | struct clk *of_clk_get_by_name(struct device_node *np, const char *name) | ||
86 | { | 89 | { |
87 | struct clk *clk = ERR_PTR(-ENOENT); | 90 | struct clk *clk = ERR_PTR(-ENOENT); |
88 | 91 | ||
@@ -97,10 +100,10 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name) | |||
97 | */ | 100 | */ |
98 | if (name) | 101 | if (name) |
99 | index = of_property_match_string(np, "clock-names", name); | 102 | index = of_property_match_string(np, "clock-names", name); |
100 | clk = of_clk_get(np, index); | 103 | clk = __of_clk_get(np, index, dev_id, name); |
101 | if (!IS_ERR(clk)) | 104 | if (!IS_ERR(clk)) { |
102 | break; | 105 | break; |
103 | else if (name && index >= 0) { | 106 | } else if (name && index >= 0) { |
104 | if (PTR_ERR(clk) != -EPROBE_DEFER) | 107 | if (PTR_ERR(clk) != -EPROBE_DEFER) |
105 | pr_err("ERROR: could not get clock %s:%s(%i)\n", | 108 | pr_err("ERROR: could not get clock %s:%s(%i)\n", |
106 | np->full_name, name ? name : "", index); | 109 | np->full_name, name ? name : "", index); |
@@ -119,7 +122,33 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name) | |||
119 | 122 | ||
120 | return clk; | 123 | return clk; |
121 | } | 124 | } |
125 | |||
126 | /** | ||
127 | * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node | ||
128 | * @np: pointer to clock consumer node | ||
129 | * @name: name of consumer's clock input, or NULL for the first clock reference | ||
130 | * | ||
131 | * This function parses the clocks and clock-names properties, | ||
132 | * and uses them to look up the struct clk from the registered list of clock | ||
133 | * providers. | ||
134 | */ | ||
135 | struct clk *of_clk_get_by_name(struct device_node *np, const char *name) | ||
136 | { | ||
137 | if (!np) | ||
138 | return ERR_PTR(-ENOENT); | ||
139 | |||
140 | return __of_clk_get_by_name(np, np->full_name, name); | ||
141 | } | ||
122 | EXPORT_SYMBOL(of_clk_get_by_name); | 142 | EXPORT_SYMBOL(of_clk_get_by_name); |
143 | |||
144 | #else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */ | ||
145 | |||
146 | static struct clk *__of_clk_get_by_name(struct device_node *np, | ||
147 | const char *dev_id, | ||
148 | const char *name) | ||
149 | { | ||
150 | return ERR_PTR(-ENOENT); | ||
151 | } | ||
123 | #endif | 152 | #endif |
124 | 153 | ||
125 | /* | 154 | /* |
@@ -168,14 +197,28 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) | |||
168 | struct clk *clk_get_sys(const char *dev_id, const char *con_id) | 197 | struct clk *clk_get_sys(const char *dev_id, const char *con_id) |
169 | { | 198 | { |
170 | struct clk_lookup *cl; | 199 | struct clk_lookup *cl; |
200 | struct clk *clk = NULL; | ||
171 | 201 | ||
172 | mutex_lock(&clocks_mutex); | 202 | mutex_lock(&clocks_mutex); |
203 | |||
173 | cl = clk_find(dev_id, con_id); | 204 | cl = clk_find(dev_id, con_id); |
174 | if (cl && !__clk_get(cl->clk)) | 205 | if (!cl) |
206 | goto out; | ||
207 | |||
208 | clk = __clk_create_clk(__clk_get_hw(cl->clk), dev_id, con_id); | ||
209 | if (IS_ERR(clk)) | ||
210 | goto out; | ||
211 | |||
212 | if (!__clk_get(clk)) { | ||
213 | __clk_free_clk(clk); | ||
175 | cl = NULL; | 214 | cl = NULL; |
215 | goto out; | ||
216 | } | ||
217 | |||
218 | out: | ||
176 | mutex_unlock(&clocks_mutex); | 219 | mutex_unlock(&clocks_mutex); |
177 | 220 | ||
178 | return cl ? cl->clk : ERR_PTR(-ENOENT); | 221 | return cl ? clk : ERR_PTR(-ENOENT); |
179 | } | 222 | } |
180 | EXPORT_SYMBOL(clk_get_sys); | 223 | EXPORT_SYMBOL(clk_get_sys); |
181 | 224 | ||
@@ -185,10 +228,8 @@ struct clk *clk_get(struct device *dev, const char *con_id) | |||
185 | struct clk *clk; | 228 | struct clk *clk; |
186 | 229 | ||
187 | if (dev) { | 230 | if (dev) { |
188 | clk = of_clk_get_by_name(dev->of_node, con_id); | 231 | clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id); |
189 | if (!IS_ERR(clk)) | 232 | if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER) |
190 | return clk; | ||
191 | if (PTR_ERR(clk) == -EPROBE_DEFER) | ||
192 | return clk; | 233 | return clk; |
193 | } | 234 | } |
194 | 235 | ||
@@ -331,6 +372,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id, | |||
331 | 372 | ||
332 | return 0; | 373 | return 0; |
333 | } | 374 | } |
375 | EXPORT_SYMBOL(clk_register_clkdev); | ||
334 | 376 | ||
335 | /** | 377 | /** |
336 | * clk_register_clkdevs - register a set of clk_lookup for a struct clk | 378 | * clk_register_clkdevs - register a set of clk_lookup for a struct clk |