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 : : static LIST_HEAD(clocks);
25 : : static DEFINE_MUTEX(clocks_mutex);
26 : :
27 : : #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
28 : 0 : 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 [ # # ]: 0 : if (index < 0)
35 : : return ERR_PTR(-EINVAL);
36 : :
37 : 0 : rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
38 : : &clkspec);
39 [ # # ]: 0 : if (rc)
40 : 0 : return ERR_PTR(rc);
41 : :
42 : 0 : clk = of_clk_get_from_provider(&clkspec);
43 : : of_node_put(clkspec.np);
44 : 0 : 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 : 0 : 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 [ # # ]: 0 : 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 [ # # ]: 0 : if (name)
71 : 0 : index = of_property_match_string(np, "clock-names", name);
72 : 0 : clk = of_clk_get(np, index);
73 [ # # ]: 0 : if (!IS_ERR(clk))
74 : : break;
75 [ # # ]: 0 : else if (name && index >= 0) {
76 [ # # ]: 0 : pr_err("ERROR: could not get clock %s:%s(%i)\n",
77 : : np->full_name, name ? name : "", index);
78 : 0 : 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 : 0 : np = np->parent;
87 [ # # ][ # # ]: 0 : if (np && !of_get_property(np, "clock-ranges", NULL))
88 : : break;
89 : : }
90 : :
91 : 0 : return clk;
92 : : }
93 : : EXPORT_SYMBOL(of_clk_get_by_name);
94 : : #endif
95 : :
96 : : /*
97 : : * Find the correct struct clk for the device and connection ID.
98 : : * We do slightly fuzzy matching here:
99 : : * An entry with a NULL ID is assumed to be a wildcard.
100 : : * If an entry has a device ID, it must match
101 : : * If an entry has a connection ID, it must match
102 : : * Then we take the most specific entry - with the following
103 : : * order of precedence: dev+con > dev only > con only.
104 : : */
105 : 0 : static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
106 : : {
107 : : struct clk_lookup *p, *cl = NULL;
108 : : int match, best_found = 0, best_possible = 0;
109 : :
110 [ # # ]: 0 : if (dev_id)
111 : : best_possible += 2;
112 [ # # ]: 0 : if (con_id)
113 : 0 : best_possible += 1;
114 : :
115 [ # # ]: 0 : list_for_each_entry(p, &clocks, node) {
116 : : match = 0;
117 [ # # ]: 0 : if (p->dev_id) {
118 [ # # ][ # # ]: 0 : if (!dev_id || strcmp(p->dev_id, dev_id))
119 : 0 : continue;
120 : : match += 2;
121 : : }
122 [ # # ]: 0 : if (p->con_id) {
123 [ # # ][ # # ]: 0 : if (!con_id || strcmp(p->con_id, con_id))
124 : 0 : continue;
125 : 0 : match += 1;
126 : : }
127 : :
128 [ # # ]: 0 : if (match > best_found) {
129 : : cl = p;
130 [ # # ]: 0 : if (match != best_possible)
131 : : best_found = match;
132 : : else
133 : : break;
134 : : }
135 : : }
136 : 0 : return cl;
137 : : }
138 : :
139 : 0 : struct clk *clk_get_sys(const char *dev_id, const char *con_id)
140 : : {
141 : : struct clk_lookup *cl;
142 : :
143 : 0 : mutex_lock(&clocks_mutex);
144 : 0 : cl = clk_find(dev_id, con_id);
145 : : if (cl && !__clk_get(cl->clk))
146 : : cl = NULL;
147 : 0 : mutex_unlock(&clocks_mutex);
148 : :
149 [ # # ]: 0 : return cl ? cl->clk : ERR_PTR(-ENOENT);
150 : : }
151 : : EXPORT_SYMBOL(clk_get_sys);
152 : :
153 : 0 : struct clk *clk_get(struct device *dev, const char *con_id)
154 : : {
155 [ # # ]: 0 : const char *dev_id = dev ? dev_name(dev) : NULL;
156 : : struct clk *clk;
157 : :
158 [ # # ]: 0 : if (dev) {
159 : 0 : clk = of_clk_get_by_name(dev->of_node, con_id);
160 [ # # ]: 0 : if (!IS_ERR(clk) && __clk_get(clk))
161 : : return clk;
162 : : }
163 : :
164 : 0 : return clk_get_sys(dev_id, con_id);
165 : : }
166 : : EXPORT_SYMBOL(clk_get);
167 : :
168 : 0 : void clk_put(struct clk *clk)
169 : : {
170 : : __clk_put(clk);
171 : 0 : }
172 : : EXPORT_SYMBOL(clk_put);
173 : :
174 : 0 : void clkdev_add(struct clk_lookup *cl)
175 : : {
176 : 0 : mutex_lock(&clocks_mutex);
177 : 0 : list_add_tail(&cl->node, &clocks);
178 : 0 : mutex_unlock(&clocks_mutex);
179 : 0 : }
180 : : EXPORT_SYMBOL(clkdev_add);
181 : :
182 : 0 : void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
183 : : {
184 : 0 : mutex_lock(&clocks_mutex);
185 [ # # ]: 0 : while (num--) {
186 : 0 : list_add_tail(&cl->node, &clocks);
187 : 0 : cl++;
188 : : }
189 : 0 : mutex_unlock(&clocks_mutex);
190 : 0 : }
191 : :
192 : : #define MAX_DEV_ID 20
193 : : #define MAX_CON_ID 16
194 : :
195 : : struct clk_lookup_alloc {
196 : : struct clk_lookup cl;
197 : : char dev_id[MAX_DEV_ID];
198 : : char con_id[MAX_CON_ID];
199 : : };
200 : :
201 : : static struct clk_lookup * __init_refok
202 : 0 : vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt,
203 : : va_list ap)
204 : : {
205 : : struct clk_lookup_alloc *cla;
206 : :
207 : : cla = __clkdev_alloc(sizeof(*cla));
208 [ # # ]: 0 : if (!cla)
209 : : return NULL;
210 : :
211 : 0 : cla->cl.clk = clk;
212 [ # # ]: 0 : if (con_id) {
213 : 0 : strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
214 : 0 : cla->cl.con_id = cla->con_id;
215 : : }
216 : :
217 [ # # ]: 0 : if (dev_fmt) {
218 : 0 : vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
219 : 0 : cla->cl.dev_id = cla->dev_id;
220 : : }
221 : :
222 : 0 : return &cla->cl;
223 : : }
224 : :
225 : : struct clk_lookup * __init_refok
226 : 0 : clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
227 : : {
228 : : struct clk_lookup *cl;
229 : : va_list ap;
230 : :
231 : 0 : va_start(ap, dev_fmt);
232 : 0 : cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
233 : 0 : va_end(ap);
234 : :
235 : 0 : return cl;
236 : : }
237 : : EXPORT_SYMBOL(clkdev_alloc);
238 : :
239 : 0 : int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
240 : : struct device *dev)
241 : : {
242 : 0 : struct clk *r = clk_get(dev, id);
243 : : struct clk_lookup *l;
244 : :
245 [ # # ]: 0 : if (IS_ERR(r))
246 : 0 : return PTR_ERR(r);
247 : :
248 : 0 : l = clkdev_alloc(r, alias, alias_dev_name);
249 : : clk_put(r);
250 [ # # ]: 0 : if (!l)
251 : : return -ENODEV;
252 : 0 : clkdev_add(l);
253 : 0 : return 0;
254 : : }
255 : : EXPORT_SYMBOL(clk_add_alias);
256 : :
257 : : /*
258 : : * clkdev_drop - remove a clock dynamically allocated
259 : : */
260 : 0 : void clkdev_drop(struct clk_lookup *cl)
261 : : {
262 : 0 : mutex_lock(&clocks_mutex);
263 : : list_del(&cl->node);
264 : 0 : mutex_unlock(&clocks_mutex);
265 : 0 : kfree(cl);
266 : 0 : }
267 : : EXPORT_SYMBOL(clkdev_drop);
268 : :
269 : : /**
270 : : * clk_register_clkdev - register one clock lookup for a struct clk
271 : : * @clk: struct clk to associate with all clk_lookups
272 : : * @con_id: connection ID string on device
273 : : * @dev_id: format string describing device name
274 : : *
275 : : * con_id or dev_id may be NULL as a wildcard, just as in the rest of
276 : : * clkdev.
277 : : *
278 : : * To make things easier for mass registration, we detect error clks
279 : : * from a previous clk_register() call, and return the error code for
280 : : * those. This is to permit this function to be called immediately
281 : : * after clk_register().
282 : : */
283 : 0 : int clk_register_clkdev(struct clk *clk, const char *con_id,
284 : : const char *dev_fmt, ...)
285 : : {
286 : : struct clk_lookup *cl;
287 : : va_list ap;
288 : :
289 [ # # ]: 0 : if (IS_ERR(clk))
290 : 0 : return PTR_ERR(clk);
291 : :
292 : 0 : va_start(ap, dev_fmt);
293 : 0 : cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
294 : 0 : va_end(ap);
295 : :
296 [ # # ]: 0 : if (!cl)
297 : : return -ENOMEM;
298 : :
299 : 0 : clkdev_add(cl);
300 : :
301 : 0 : return 0;
302 : : }
303 : :
304 : : /**
305 : : * clk_register_clkdevs - register a set of clk_lookup for a struct clk
306 : : * @clk: struct clk to associate with all clk_lookups
307 : : * @cl: array of clk_lookup structures with con_id and dev_id pre-initialized
308 : : * @num: number of clk_lookup structures to register
309 : : *
310 : : * To make things easier for mass registration, we detect error clks
311 : : * from a previous clk_register() call, and return the error code for
312 : : * those. This is to permit this function to be called immediately
313 : : * after clk_register().
314 : : */
315 : 0 : int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num)
316 : : {
317 : : unsigned i;
318 : :
319 [ # # ]: 0 : if (IS_ERR(clk))
320 : 0 : return PTR_ERR(clk);
321 : :
322 [ # # ]: 0 : for (i = 0; i < num; i++, cl++) {
323 : 0 : cl->clk = clk;
324 : 0 : clkdev_add(cl);
325 : : }
326 : :
327 : : return 0;
328 : : }
329 : : EXPORT_SYMBOL(clk_register_clkdevs);
|