Commit | Line | Data |
---|---|---|
0318e693 | 1 | /* |
6d803ba7 | 2 | * drivers/clk/clkdev.c |
0318e693 RK |
3 | * |
4 | * Copyright (C) 2008 Russell King. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | * Helper for the clk API to assist looking up a struct clk. | |
11 | */ | |
12 | #include <linux/module.h> | |
13 | #include <linux/kernel.h> | |
14 | #include <linux/device.h> | |
15 | #include <linux/list.h> | |
16 | #include <linux/errno.h> | |
17 | #include <linux/err.h> | |
18 | #include <linux/string.h> | |
19 | #include <linux/mutex.h> | |
c0c60c4b | 20 | #include <linux/clk.h> |
6d803ba7 | 21 | #include <linux/clkdev.h> |
766e6a4e | 22 | #include <linux/of.h> |
0318e693 | 23 | |
3a3d2b05 SN |
24 | #include "clk.h" |
25 | ||
0318e693 RK |
26 | static LIST_HEAD(clocks); |
27 | static DEFINE_MUTEX(clocks_mutex); | |
28 | ||
137f8a72 | 29 | #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) |
766e6a4e GL |
30 | struct clk *of_clk_get(struct device_node *np, int index) |
31 | { | |
32 | struct of_phandle_args clkspec; | |
33 | struct clk *clk; | |
34 | int rc; | |
35 | ||
36 | if (index < 0) | |
37 | return ERR_PTR(-EINVAL); | |
38 | ||
39 | rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index, | |
40 | &clkspec); | |
41 | if (rc) | |
42 | return ERR_PTR(rc); | |
43 | ||
3a3d2b05 SN |
44 | of_clk_lock(); |
45 | clk = __of_clk_get_from_provider(&clkspec); | |
46 | ||
47 | if (!IS_ERR(clk) && !__clk_get(clk)) | |
48 | clk = ERR_PTR(-ENOENT); | |
49 | ||
50 | of_clk_unlock(); | |
766e6a4e GL |
51 | of_node_put(clkspec.np); |
52 | return clk; | |
53 | } | |
54 | EXPORT_SYMBOL(of_clk_get); | |
55 | ||
56 | /** | |
57 | * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node | |
58 | * @np: pointer to clock consumer node | |
59 | * @name: name of consumer's clock input, or NULL for the first clock reference | |
60 | * | |
61 | * This function parses the clocks and clock-names properties, | |
62 | * and uses them to look up the struct clk from the registered list of clock | |
63 | * providers. | |
64 | */ | |
65 | struct clk *of_clk_get_by_name(struct device_node *np, const char *name) | |
66 | { | |
67 | struct clk *clk = ERR_PTR(-ENOENT); | |
68 | ||
69 | /* Walk up the tree of devices looking for a clock that matches */ | |
70 | while (np) { | |
71 | int index = 0; | |
72 | ||
73 | /* | |
74 | * For named clocks, first look up the name in the | |
75 | * "clock-names" property. If it cannot be found, then | |
76 | * index will be an error code, and of_clk_get() will fail. | |
77 | */ | |
78 | if (name) | |
79 | index = of_property_match_string(np, "clock-names", name); | |
80 | clk = of_clk_get(np, index); | |
81 | if (!IS_ERR(clk)) | |
82 | break; | |
83 | else if (name && index >= 0) { | |
84 | pr_err("ERROR: could not get clock %s:%s(%i)\n", | |
85 | np->full_name, name ? name : "", index); | |
86 | return clk; | |
87 | } | |
88 | ||
89 | /* | |
90 | * No matching clock found on this node. If the parent node | |
91 | * has a "clock-ranges" property, then we can try one of its | |
92 | * clocks. | |
93 | */ | |
94 | np = np->parent; | |
95 | if (np && !of_get_property(np, "clock-ranges", NULL)) | |
96 | break; | |
97 | } | |
98 | ||
99 | return clk; | |
100 | } | |
101 | EXPORT_SYMBOL(of_clk_get_by_name); | |
102 | #endif | |
103 | ||
409dc360 RK |
104 | /* |
105 | * Find the correct struct clk for the device and connection ID. | |
106 | * We do slightly fuzzy matching here: | |
107 | * An entry with a NULL ID is assumed to be a wildcard. | |
108 | * If an entry has a device ID, it must match | |
109 | * If an entry has a connection ID, it must match | |
110 | * Then we take the most specific entry - with the following | |
659431fc | 111 | * order of precedence: dev+con > dev only > con only. |
409dc360 | 112 | */ |
e8bf8df9 | 113 | static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) |
0318e693 | 114 | { |
e8bf8df9 | 115 | struct clk_lookup *p, *cl = NULL; |
67b50871 | 116 | int match, best_found = 0, best_possible = 0; |
117 | ||
118 | if (dev_id) | |
119 | best_possible += 2; | |
120 | if (con_id) | |
121 | best_possible += 1; | |
0318e693 RK |
122 | |
123 | list_for_each_entry(p, &clocks, node) { | |
0318e693 | 124 | match = 0; |
409dc360 RK |
125 | if (p->dev_id) { |
126 | if (!dev_id || strcmp(p->dev_id, dev_id)) | |
127 | continue; | |
128 | match += 2; | |
129 | } | |
130 | if (p->con_id) { | |
131 | if (!con_id || strcmp(p->con_id, con_id)) | |
132 | continue; | |
133 | match += 1; | |
134 | } | |
0318e693 | 135 | |
67b50871 | 136 | if (match > best_found) { |
e8bf8df9 | 137 | cl = p; |
67b50871 | 138 | if (match != best_possible) |
139 | best_found = match; | |
e4bf5bec | 140 | else |
141 | break; | |
0318e693 RK |
142 | } |
143 | } | |
e8bf8df9 | 144 | return cl; |
0318e693 RK |
145 | } |
146 | ||
05fd8e73 | 147 | struct clk *clk_get_sys(const char *dev_id, const char *con_id) |
0318e693 | 148 | { |
e8bf8df9 | 149 | struct clk_lookup *cl; |
0318e693 RK |
150 | |
151 | mutex_lock(&clocks_mutex); | |
e8bf8df9 RK |
152 | cl = clk_find(dev_id, con_id); |
153 | if (cl && !__clk_get(cl->clk)) | |
154 | cl = NULL; | |
0318e693 RK |
155 | mutex_unlock(&clocks_mutex); |
156 | ||
e8bf8df9 | 157 | return cl ? cl->clk : ERR_PTR(-ENOENT); |
0318e693 | 158 | } |
05fd8e73 SH |
159 | EXPORT_SYMBOL(clk_get_sys); |
160 | ||
161 | struct clk *clk_get(struct device *dev, const char *con_id) | |
162 | { | |
163 | const char *dev_id = dev ? dev_name(dev) : NULL; | |
766e6a4e GL |
164 | struct clk *clk; |
165 | ||
166 | if (dev) { | |
167 | clk = of_clk_get_by_name(dev->of_node, con_id); | |
3a3d2b05 | 168 | if (!IS_ERR(clk)) |
766e6a4e GL |
169 | return clk; |
170 | } | |
05fd8e73 SH |
171 | |
172 | return clk_get_sys(dev_id, con_id); | |
173 | } | |
0318e693 RK |
174 | EXPORT_SYMBOL(clk_get); |
175 | ||
176 | void clk_put(struct clk *clk) | |
177 | { | |
178 | __clk_put(clk); | |
179 | } | |
180 | EXPORT_SYMBOL(clk_put); | |
181 | ||
182 | void clkdev_add(struct clk_lookup *cl) | |
183 | { | |
184 | mutex_lock(&clocks_mutex); | |
185 | list_add_tail(&cl->node, &clocks); | |
186 | mutex_unlock(&clocks_mutex); | |
187 | } | |
188 | EXPORT_SYMBOL(clkdev_add); | |
189 | ||
0a0300dc RK |
190 | void __init clkdev_add_table(struct clk_lookup *cl, size_t num) |
191 | { | |
192 | mutex_lock(&clocks_mutex); | |
193 | while (num--) { | |
194 | list_add_tail(&cl->node, &clocks); | |
195 | cl++; | |
196 | } | |
197 | mutex_unlock(&clocks_mutex); | |
198 | } | |
199 | ||
0318e693 RK |
200 | #define MAX_DEV_ID 20 |
201 | #define MAX_CON_ID 16 | |
202 | ||
203 | struct clk_lookup_alloc { | |
204 | struct clk_lookup cl; | |
205 | char dev_id[MAX_DEV_ID]; | |
206 | char con_id[MAX_CON_ID]; | |
207 | }; | |
208 | ||
e9d7f406 RK |
209 | static struct clk_lookup * __init_refok |
210 | vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, | |
211 | va_list ap) | |
0318e693 RK |
212 | { |
213 | struct clk_lookup_alloc *cla; | |
214 | ||
6d803ba7 | 215 | cla = __clkdev_alloc(sizeof(*cla)); |
0318e693 RK |
216 | if (!cla) |
217 | return NULL; | |
218 | ||
219 | cla->cl.clk = clk; | |
220 | if (con_id) { | |
221 | strlcpy(cla->con_id, con_id, sizeof(cla->con_id)); | |
222 | cla->cl.con_id = cla->con_id; | |
223 | } | |
224 | ||
225 | if (dev_fmt) { | |
0318e693 RK |
226 | vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap); |
227 | cla->cl.dev_id = cla->dev_id; | |
0318e693 RK |
228 | } |
229 | ||
230 | return &cla->cl; | |
231 | } | |
e9d7f406 RK |
232 | |
233 | struct clk_lookup * __init_refok | |
234 | clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...) | |
235 | { | |
236 | struct clk_lookup *cl; | |
237 | va_list ap; | |
238 | ||
239 | va_start(ap, dev_fmt); | |
240 | cl = vclkdev_alloc(clk, con_id, dev_fmt, ap); | |
241 | va_end(ap); | |
242 | ||
243 | return cl; | |
244 | } | |
0318e693 RK |
245 | EXPORT_SYMBOL(clkdev_alloc); |
246 | ||
c0683039 TL |
247 | int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, |
248 | struct device *dev) | |
249 | { | |
250 | struct clk *r = clk_get(dev, id); | |
251 | struct clk_lookup *l; | |
252 | ||
253 | if (IS_ERR(r)) | |
254 | return PTR_ERR(r); | |
255 | ||
256 | l = clkdev_alloc(r, alias, alias_dev_name); | |
257 | clk_put(r); | |
258 | if (!l) | |
259 | return -ENODEV; | |
260 | clkdev_add(l); | |
261 | return 0; | |
262 | } | |
263 | EXPORT_SYMBOL(clk_add_alias); | |
264 | ||
0318e693 RK |
265 | /* |
266 | * clkdev_drop - remove a clock dynamically allocated | |
267 | */ | |
268 | void clkdev_drop(struct clk_lookup *cl) | |
269 | { | |
270 | mutex_lock(&clocks_mutex); | |
271 | list_del(&cl->node); | |
272 | mutex_unlock(&clocks_mutex); | |
273 | kfree(cl); | |
274 | } | |
275 | EXPORT_SYMBOL(clkdev_drop); | |
e9d7f406 RK |
276 | |
277 | /** | |
278 | * clk_register_clkdev - register one clock lookup for a struct clk | |
279 | * @clk: struct clk to associate with all clk_lookups | |
280 | * @con_id: connection ID string on device | |
281 | * @dev_id: format string describing device name | |
282 | * | |
283 | * con_id or dev_id may be NULL as a wildcard, just as in the rest of | |
284 | * clkdev. | |
285 | * | |
286 | * To make things easier for mass registration, we detect error clks | |
287 | * from a previous clk_register() call, and return the error code for | |
288 | * those. This is to permit this function to be called immediately | |
289 | * after clk_register(). | |
290 | */ | |
291 | int clk_register_clkdev(struct clk *clk, const char *con_id, | |
292 | const char *dev_fmt, ...) | |
293 | { | |
294 | struct clk_lookup *cl; | |
295 | va_list ap; | |
296 | ||
297 | if (IS_ERR(clk)) | |
298 | return PTR_ERR(clk); | |
299 | ||
300 | va_start(ap, dev_fmt); | |
301 | cl = vclkdev_alloc(clk, con_id, dev_fmt, ap); | |
302 | va_end(ap); | |
303 | ||
304 | if (!cl) | |
305 | return -ENOMEM; | |
306 | ||
307 | clkdev_add(cl); | |
308 | ||
309 | return 0; | |
310 | } | |
311 | ||
312 | /** | |
313 | * clk_register_clkdevs - register a set of clk_lookup for a struct clk | |
314 | * @clk: struct clk to associate with all clk_lookups | |
315 | * @cl: array of clk_lookup structures with con_id and dev_id pre-initialized | |
316 | * @num: number of clk_lookup structures to register | |
317 | * | |
318 | * To make things easier for mass registration, we detect error clks | |
319 | * from a previous clk_register() call, and return the error code for | |
320 | * those. This is to permit this function to be called immediately | |
321 | * after clk_register(). | |
322 | */ | |
323 | int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num) | |
324 | { | |
325 | unsigned i; | |
326 | ||
327 | if (IS_ERR(clk)) | |
328 | return PTR_ERR(clk); | |
329 | ||
330 | for (i = 0; i < num; i++, cl++) { | |
331 | cl->clk = clk; | |
332 | clkdev_add(cl); | |
333 | } | |
334 | ||
335 | return 0; | |
336 | } | |
337 | EXPORT_SYMBOL(clk_register_clkdevs); |