Branch data Line data Source code
1 : : /*
2 : : * drivers/clk/clkdev.c
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>
20 : : #include <linux/clk.h>
21 : : #include <linux/clkdev.h>
22 : : #include <linux/of.h>
23 : :
24 : : #include "clk.h"
25 : :
26 : : static LIST_HEAD(clocks);
27 : : static DEFINE_MUTEX(clocks_mutex);
28 : :
29 : : #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
30 : 0 : 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 [ - + ]: 3 : if (index < 0)
37 : : return ERR_PTR(-EINVAL);
38 : :
39 : 0 : rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
40 : : &clkspec);
41 [ # # ]: 0 : if (rc)
42 : 0 : return ERR_PTR(rc);
43 : :
44 : 0 : of_clk_lock();
45 : 0 : clk = __of_clk_get_from_provider(&clkspec);
46 : :
47 [ # # ][ # # ]: 0 : if (!IS_ERR(clk) && !__clk_get(clk))
48 : : clk = ERR_PTR(-ENOENT);
49 : :
50 : 0 : of_clk_unlock();
51 : : of_node_put(clkspec.np);
52 : 0 : 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 : 0 : 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 [ + - ]: 3 : 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 [ + - ]: 3 : if (name)
79 : 3 : index = of_property_match_string(np, "clock-names", name);
80 : 3 : clk = of_clk_get(np, index);
81 [ + - ]: 3 : if (!IS_ERR(clk))
82 : : break;
83 [ - + ]: 3 : else if (name && index >= 0) {
84 [ # # ]: 0 : pr_err("ERROR: could not get clock %s:%s(%i)\n",
85 : : np->full_name, name ? name : "", index);
86 : 0 : 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 : 3 : np = np->parent;
95 [ + - ][ - + ]: 3 : if (np && !of_get_property(np, "clock-ranges", NULL))
96 : : break;
97 : : }
98 : :
99 : 3 : return clk;
100 : : }
101 : : EXPORT_SYMBOL(of_clk_get_by_name);
102 : : #endif
103 : :
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
111 : : * order of precedence: dev+con > dev only > con only.
112 : : */
113 : 0 : static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
114 : : {
115 : : struct clk_lookup *p, *cl = NULL;
116 : : int match, best_found = 0, best_possible = 0;
117 : :
118 [ + - ]: 3 : if (dev_id)
119 : : best_possible += 2;
120 [ + - ]: 3 : if (con_id)
121 : 3 : best_possible += 1;
122 : :
123 [ + + ]: 18 : list_for_each_entry(p, &clocks, node) {
124 : : match = 0;
125 [ + - ]: 15 : if (p->dev_id) {
126 [ + - ][ + + ]: 15 : if (!dev_id || strcmp(p->dev_id, dev_id))
127 : 12 : continue;
128 : : match += 2;
129 : : }
130 [ - + ]: 3 : if (p->con_id) {
131 [ # # ][ # # ]: 0 : if (!con_id || strcmp(p->con_id, con_id))
132 : 0 : continue;
133 : 0 : match += 1;
134 : : }
135 : :
136 [ # # ]: 3 : if (match > best_found) {
137 : : cl = p;
138 [ + ]: 3 : if (match != best_possible)
139 : : best_found = match;
140 : : else
141 : : break;
142 : : }
143 : : }
144 : 0 : return cl;
145 : : }
146 : :
147 : 0 : struct clk *clk_get_sys(const char *dev_id, const char *con_id)
148 : : {
149 : : struct clk_lookup *cl;
150 : :
151 : 3 : mutex_lock(&clocks_mutex);
152 : 3 : cl = clk_find(dev_id, con_id);
153 [ + - ][ - + ]: 3 : if (cl && !__clk_get(cl->clk))
154 : : cl = NULL;
155 : 3 : mutex_unlock(&clocks_mutex);
156 : :
157 [ + - ]: 3 : return cl ? cl->clk : ERR_PTR(-ENOENT);
158 : : }
159 : : EXPORT_SYMBOL(clk_get_sys);
160 : :
161 : 0 : struct clk *clk_get(struct device *dev, const char *con_id)
162 : : {
163 [ + - ]: 3 : const char *dev_id = dev ? dev_name(dev) : NULL;
164 : : struct clk *clk;
165 : :
166 [ + - ]: 3 : if (dev) {
167 : 3 : clk = of_clk_get_by_name(dev->of_node, con_id);
168 [ + - ]: 3 : if (!IS_ERR(clk))
169 : : return clk;
170 : : }
171 : :
172 : 3 : return clk_get_sys(dev_id, con_id);
173 : : }
174 : : EXPORT_SYMBOL(clk_get);
175 : :
176 : 0 : void clk_put(struct clk *clk)
177 : : {
178 : 3 : __clk_put(clk);
179 : 3 : }
180 : : EXPORT_SYMBOL(clk_put);
181 : :
182 : 0 : void clkdev_add(struct clk_lookup *cl)
183 : : {
184 : 0 : mutex_lock(&clocks_mutex);
185 : 0 : list_add_tail(&cl->node, &clocks);
186 : 0 : mutex_unlock(&clocks_mutex);
187 : 0 : }
188 : : EXPORT_SYMBOL(clkdev_add);
189 : :
190 : 0 : void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
191 : : {
192 : 0 : mutex_lock(&clocks_mutex);
193 [ # # ]: 0 : while (num--) {
194 : 0 : list_add_tail(&cl->node, &clocks);
195 : 0 : cl++;
196 : : }
197 : 0 : mutex_unlock(&clocks_mutex);
198 : 0 : }
199 : :
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 : :
209 : : static struct clk_lookup * __init_refok
210 : 0 : vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt,
211 : : va_list ap)
212 : : {
213 : : struct clk_lookup_alloc *cla;
214 : :
215 : : cla = __clkdev_alloc(sizeof(*cla));
216 [ # # ]: 0 : if (!cla)
217 : : return NULL;
218 : :
219 : 0 : cla->cl.clk = clk;
220 [ # # ]: 0 : if (con_id) {
221 : 0 : strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
222 : 0 : cla->cl.con_id = cla->con_id;
223 : : }
224 : :
225 [ # # ]: 0 : if (dev_fmt) {
226 : 0 : vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
227 : 0 : cla->cl.dev_id = cla->dev_id;
228 : : }
229 : :
230 : 0 : return &cla->cl;
231 : : }
232 : :
233 : : struct clk_lookup * __init_refok
234 : 0 : 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 : 0 : va_start(ap, dev_fmt);
240 : 0 : cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
241 : 0 : va_end(ap);
242 : :
243 : 0 : return cl;
244 : : }
245 : : EXPORT_SYMBOL(clkdev_alloc);
246 : :
247 : 0 : int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
248 : : struct device *dev)
249 : : {
250 : 0 : struct clk *r = clk_get(dev, id);
251 : : struct clk_lookup *l;
252 : :
253 [ # # ]: 0 : if (IS_ERR(r))
254 : 0 : return PTR_ERR(r);
255 : :
256 : 0 : l = clkdev_alloc(r, alias, alias_dev_name);
257 : : clk_put(r);
258 [ # # ]: 0 : if (!l)
259 : : return -ENODEV;
260 : 0 : clkdev_add(l);
261 : 0 : return 0;
262 : : }
263 : : EXPORT_SYMBOL(clk_add_alias);
264 : :
265 : : /*
266 : : * clkdev_drop - remove a clock dynamically allocated
267 : : */
268 : 0 : void clkdev_drop(struct clk_lookup *cl)
269 : : {
270 : 0 : mutex_lock(&clocks_mutex);
271 : : list_del(&cl->node);
272 : 0 : mutex_unlock(&clocks_mutex);
273 : 0 : kfree(cl);
274 : 0 : }
275 : : EXPORT_SYMBOL(clkdev_drop);
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 : 0 : 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 [ # # ]: 0 : if (IS_ERR(clk))
298 : 0 : return PTR_ERR(clk);
299 : :
300 : 0 : va_start(ap, dev_fmt);
301 : 0 : cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
302 : 0 : va_end(ap);
303 : :
304 [ # # ]: 0 : if (!cl)
305 : : return -ENOMEM;
306 : :
307 : 0 : clkdev_add(cl);
308 : :
309 : 0 : 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 : 0 : int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num)
324 : : {
325 : : unsigned i;
326 : :
327 [ # # ]: 0 : if (IS_ERR(clk))
328 : 0 : return PTR_ERR(clk);
329 : :
330 [ # # ]: 0 : for (i = 0; i < num; i++, cl++) {
331 : 0 : cl->clk = clk;
332 : 0 : clkdev_add(cl);
333 : : }
334 : :
335 : : return 0;
336 : : }
337 : : EXPORT_SYMBOL(clk_register_clkdevs);
|