Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
clkdev.c
Go to the documentation of this file.
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 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 
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 
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 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  if (dev_id)
111  best_possible += 2;
112  if (con_id)
113  best_possible += 1;
114 
115  list_for_each_entry(p, &clocks, node) {
116  match = 0;
117  if (p->dev_id) {
118  if (!dev_id || strcmp(p->dev_id, dev_id))
119  continue;
120  match += 2;
121  }
122  if (p->con_id) {
123  if (!con_id || strcmp(p->con_id, con_id))
124  continue;
125  match += 1;
126  }
127 
128  if (match > best_found) {
129  cl = p;
130  if (match != best_possible)
131  best_found = match;
132  else
133  break;
134  }
135  }
136  return cl;
137 }
138 
139 struct clk *clk_get_sys(const char *dev_id, const char *con_id)
140 {
141  struct clk_lookup *cl;
142 
143  mutex_lock(&clocks_mutex);
144  cl = clk_find(dev_id, con_id);
145  if (cl && !__clk_get(cl->clk))
146  cl = NULL;
147  mutex_unlock(&clocks_mutex);
148 
149  return cl ? cl->clk : ERR_PTR(-ENOENT);
150 }
152 
153 struct clk *clk_get(struct device *dev, const char *con_id)
154 {
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 (!IS_ERR(clk) && __clk_get(clk))
161  return clk;
162  }
163 
164  return clk_get_sys(dev_id, con_id);
165 }
167 
168 void clk_put(struct clk *clk)
169 {
170  __clk_put(clk);
171 }
173 
174 void clkdev_add(struct clk_lookup *cl)
175 {
176  mutex_lock(&clocks_mutex);
177  list_add_tail(&cl->node, &clocks);
178  mutex_unlock(&clocks_mutex);
179 }
181 
182 void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
183 {
184  mutex_lock(&clocks_mutex);
185  while (num--) {
186  list_add_tail(&cl->node, &clocks);
187  cl++;
188  }
189  mutex_unlock(&clocks_mutex);
190 }
191 
192 #define MAX_DEV_ID 20
193 #define MAX_CON_ID 16
194 
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 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  if (!cla)
209  return NULL;
210 
211  cla->cl.clk = clk;
212  if (con_id) {
213  strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
214  cla->cl.con_id = cla->con_id;
215  }
216 
217  if (dev_fmt) {
218  vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
219  cla->cl.dev_id = cla->dev_id;
220  }
221 
222  return &cla->cl;
223 }
224 
225 struct clk_lookup * __init_refok
226 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  va_start(ap, dev_fmt);
232  cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
233  va_end(ap);
234 
235  return cl;
236 }
238 
239 int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
240  struct device *dev)
241 {
242  struct clk *r = clk_get(dev, id);
243  struct clk_lookup *l;
244 
245  if (IS_ERR(r))
246  return PTR_ERR(r);
247 
248  l = clkdev_alloc(r, alias, alias_dev_name);
249  clk_put(r);
250  if (!l)
251  return -ENODEV;
252  clkdev_add(l);
253  return 0;
254 }
256 
257 /*
258  * clkdev_drop - remove a clock dynamically allocated
259  */
260 void clkdev_drop(struct clk_lookup *cl)
261 {
262  mutex_lock(&clocks_mutex);
263  list_del(&cl->node);
264  mutex_unlock(&clocks_mutex);
265  kfree(cl);
266 }
268 
283 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  if (IS_ERR(clk))
290  return PTR_ERR(clk);
291 
292  va_start(ap, dev_fmt);
293  cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
294  va_end(ap);
295 
296  if (!cl)
297  return -ENOMEM;
298 
299  clkdev_add(cl);
300 
301  return 0;
302 }
303 
315 int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num)
316 {
317  unsigned i;
318 
319  if (IS_ERR(clk))
320  return PTR_ERR(clk);
321 
322  for (i = 0; i < num; i++, cl++) {
323  cl->clk = clk;
324  clkdev_add(cl);
325  }
326 
327  return 0;
328 }